1 module unde.games.dizzy.omega.main;
2 
3 import derelict.sdl2.mixer;
4 import derelict.sdl2.sdl;
5 import derelict.opengl3.gl3;
6 import derelict.opengl3.gl;
7 
8 import std.algorithm.comparison;
9 import std.algorithm.searching;
10 import std.concurrency;
11 import std.conv;
12 import std.format;
13 import std.functional;
14 import std.random;
15 import std.range.primitives;
16 import std.stdio;
17 import std.math;
18 
19 import std.string;
20 import core.memory;
21 import unde.games.dizzy.omega.animations.bag_bug_anim;
22 import unde.games.dizzy.omega.animations.bucket;
23 import unde.games.dizzy.omega.animations.drop;
24 import unde.games.dizzy.omega.animations.fall_platform;
25 import unde.games.dizzy.omega.animations.ground_castle;
26 import unde.games.dizzy.omega.animations.ground_cave;
27 import unde.games.dizzy.omega.animations.ground_garden;
28 import unde.games.dizzy.omega.animations.light_drop;
29 import unde.games.dizzy.omega.animations.meteorite;
30 import unde.games.dizzy.omega.animations.platform1;
31 import unde.games.dizzy.omega.animations.platform4;
32 import unde.games.dizzy.omega.animations.explosure;
33 import unde.games.dizzy.omega.animations.sky_zaks;
34 import unde.games.dizzy.omega.animations.stalagmite;
35 import unde.games.dizzy.omega.animations.stone_00;
36 import unde.games.dizzy.omega.animations.stone_01;
37 import unde.games.dizzy.omega.animations.stone_02;
38 import unde.games.dizzy.omega.animations.stones;
39 import unde.games.dizzy.omega.animations.water;
40 import unde.games.dizzy.omega.animations.lava;
41 import unde.games.dizzy.omega.animations.statical;
42 import unde.games.dizzy.omega.animations.things_sweep_away_zaks;
43 import unde.games.dizzy.omega.bird;
44 import unde.games.dizzy.omega.bug;
45 import unde.games.dizzy.omega.grasshopper;
46 import unde.games.dizzy.omega.dialogs;
47 import unde.games.dizzy.omega.dizzy;
48 import unde.games.dizzy.omega.dog;
49 import unde.games.dizzy.omega.item;
50 import unde.games.dizzy.omega.rope;
51 import unde.games.dizzy.omega.rotatable;
52 import unde.games.dizzy.omega.save_load;
53 import unde.games.dizzy.omega.scene_loader;
54 import unde.games.dizzy.omega.star;
55 import unde.games.dizzy.omega.tree;
56 import unde.games.dizzy.omega.fish;
57 import unde.games.dizzy.omega.flame;
58 import unde.games.dizzy.omega.squid;
59 import unde.games.obj_loader;
60 import unde.games.object;
61 import unde.games.renderer;
62 import unde.games.collision_detector;
63 import unde.global_state;
64 import unde.keybar.lib;
65 import unde.tick;
66 
67 enum STATE
68 {
69     NO_DIALOGS = 0,
70     INVENTORY = 1,
71     ENERGY_STAR = 2,
72     TOO_MANY_ITEMS = 3,
73     PIERCED_BY_STALAGMITE = 4,
74     PIERCED_BY_STALACTITE = 5,
75     HIT_BY_METEORITE = 6,
76     DISSOLVED_IN_ACID = 7,
77     BURNED_IN_LAVA = 8,
78     DAMAGED_BY_PIN = 9,
79     HIT_BY_ROCK = 10,
80     BURNED_IN_FLAME = 11,
81     CRUSHED_BY_PRESSURE = 12,
82     HELP = 99,
83     MARTIAN_AGRONOMIST_HELLO  = 100,
84     MARTIAN_AGRONOMIST_HELLO1 = 101,
85     MARTIAN_AGRONOMIST_HELLO2 = 102,
86     MARTIAN_AGRONOMIST_HELLO3 = 103,
87     MARTIAN_AGRONOMIST_HELLO4 = 104,
88     MARTIAN_AGRONOMIST_HELLO5 = 105,
89     MARTIAN_AGRONOMIST_HELLO6 = 106,
90     LOOKING_BOOTH_MESSAGE = 200,
91     LOOKING_BOOTH = 201,
92     DIZZY_USED_KNIFE_MESSAGE = 300,
93     DIZZY_USED_KNIFE_ANIM = 301,
94     DIZZY_THROW_BRANCH_MESSAGE = 400,
95     DIZZY_THROW_BRANCH_ANIM = 401,
96     DIZZY_CUTS_ROPE_MESSAGE = 500,
97     DIZZY_CUTS_ROPE_ANIM = 501,
98     MARTIAN_ENGINEER_GET_AWAY = 600,
99     MARTIAN_AGRONOMIST_ROPE = 700,
100     MARTIAN_ENGINEER_TAKES_PLAYER = 800,
101     DIZZY_TIED_ROPE_MESSAGE = 900,
102     DIZZY_UNTIED_ROPE_MESSAGE = 901,
103     DIZZY_UNTIED_SHORT_ROPE_MESSAGE = 902,
104     MARTIAN_CHEMIST_HELLO  = 1000,
105     MARTIAN_CHEMIST_HELLO1 = 1001,
106     MARTIAN_CHEMIST_HELLO2 = 1002,
107     MARTIAN_CHEMIST_HELLO3 = 1003,
108     MARTIAN_CHEMIST_HELLO4 = 1004,
109     MARTIAN_CHEMIST_HELLO5 = 1005,
110     DIZZY_DRINK_STUNNING_MESSAGE = 1100,
111     MARTIAN_AGRONOMIST_GIVES_BUCKET  = 1200,
112     MARTIAN_AGRONOMIST_GIVES_BUCKET1 = 1201,
113     DIZZY_TRIES_FILL_BUCKET_MESSAGE = 1300,
114     DIZZY_THROW_METEORITE_MESSAGE = 1400,
115     DIZZY_FILL_BUCKET_MESSAGE = 1500,
116     DIZZY_TRIES_WATER_FLOWERS_MESSAGE = 1600,
117     DIZZY_COVERED_BUCKET_MESSAGE = 1700,
118     DIZZY_WATER_FLOWERS_MESSAGE = 1800,
119     MARTIAN_AGRONOMIST_THANKS = 1900,
120     MARTIAN_ENGINEER_RETURNS_PLAYER  = 2000,
121     MARTIAN_ENGINEER_RETURNS_PLAYER1 = 2001,
122     MARTIAN_ENGINEER_RETURNS_PLAYER2 = 2002,
123     MARTIAN_ENGINEER_TAKES_BUCKET  = 2100,
124     MARTIAN_ENGINEER_TAKES_BUCKET1 = 2101,
125     DIZZY_HOLD_BRANCH_UNDER_DROP = 2200,
126     MARTIAN_ENGINEER_GIVES_SPADE = 2300,
127     DIZZY_DIG_MESSAGE = 2400,
128     DIZZY_DIG_ANIM = 2401,
129     BAG_FOUND = 2500,
130     DIZZY_OPEN_DOOR = 2600,
131     DIZZY_DIG2_MESSAGE = 2700,
132     DIZZY_CATCH_GRASSHOPPER_MESSAGE = 2800,
133     MARTIAN_CHEMIST_NO_GRASSHOPPER = 2900,
134     MARTIAN_CHEMIST_NO_BIRD = 2901,
135     MARTIAN_CHEMIST_NO_GRASSHOPPERS_POISON = 2902,
136     MARTIAN_CHEMIST_THANK_YOU = 3000,
137     MARTIAN_CHEMIST_NEED_WATER_FROM_LIGHT_TREE_CAVE = 3100,
138     DIZZY_PUT_STONE_MESSAGE = 3200,
139     DIZZY_TRY_CATCH_BUG_MESSAGE = 3300,
140     DIZZY_CATCH_BUG_MESSAGE = 3400,
141     DIZZY_CATCH_FISH_MESSAGE = 3500,
142     DIZZY_CATCH_SQUID_MESSAGE = 3600,
143     MARTIAN_CHEMIST_NO_BUG = 3700,
144     MARTIAN_CHEMIST_NO_FISH = 3701,
145     MARTIAN_CHEMIST_NO_SQUID = 3702,
146     MARTIAN_CHEMIST_NO_BUGS_POISON = 3703,
147     MARTIAN_ENGINEER_RETURNS_BUCKET = 3800,
148     DIZZY_TRIES_TO_GET_WATER = 3900,
149     DIZZY_PUT_GROUND_TO_THE_BUCKET = 4000,
150     DIZZY_GET_LIGHT_WATER = 4100,
151     MARTIAN_CHEMIST_GIVES_PSYCHOTROPIC_SPRAY = 4200,
152     DIZZY_SPRAYED_BUG_MESSAGE = 4300,
153     DIZZY_SPRAYED_GRASSHOPPER_MESSAGE = 4400,
154     MARTIAN_ENGINEER_GIVES_WHISTLE = 4500,
155     DIZZY_DIG3_MESSAGE = 4600,
156     NOT_ALL_ITEMS_IN_THE_CASTLE_MESSAGE = 4700,
157     ROPE_NOT_IN_THE_CASTLE_MESSAGE = 4800,
158     DIZZY_WHISTLE_MESSAGE = 4900,
159     THINGS_SWEEP_AWAY_ZAKS_ANIM = 4901,
160     ZAKS_SAYS_FAREWELL_WORD = 4902,
161     STONES_CRASHES_MESSAGE = 4903,
162     TO_BE_CONTINUED_MESSAGE = 10000,
163 }
164 
165 enum TEMP_MESSAGES
166 {
167     CANT_SAVE_IN_THE_MOVING,
168     CANT_SAVE_DURING_THE_QUEST,
169     SAVED,
170     NEGATIVE_LIVES,
171     PLAYS
172 }
173 
174 immutable string[SC] screen_names;
175 immutable string[SC] screen_names_ru;
176 
177 static this()
178 {
179     screen_names =
180     [
181         SC(-1,0): "Entrance to cave",
182         SC(0, 0): "The landing place",
183         SC(1, 0): "The cave of light tree",
184         SC(1, 2): "The cave",
185         SC(1, 4): "The cave",
186         SC(2, 0): "The valley of death",
187         SC(3, 0): "The valley of death",
188         SC(4, 0): "The martian well",
189         SC(5, 0): "Under the open sky of Mars",
190         SC(6, 0): "Entrance to the cave of an extinct volcano",
191         SC(7, 0): "In the cave",
192         SC(8, 0): "In the cave",
193         SC(9, 0): "The first Martian",
194         SC(10,0): "Farmstead of the agronomist",
195         SC(10,2): "Barn of the agronomist",
196         SC(10,4): "The booth",
197         SC(11,0): "Garden",
198         SC(12,0): "Entrance to the secret laboratory",
199         SC(13,0): "The engineer",
200         SC(14,0): "Muzzle of the volcano",
201         SC(14,-1): "Muzzle of the volcano",
202         SC(15,0): "Chemical laboratory",
203         SC(16,0): "Cave corridor",
204         SC(17,0): "Corridor in the cave",
205         SC(18,0): "Exit from the cave of volcano",
206         SC(19,0): "Walls of the castle",
207         SC(19,1): "Walls of the castle",
208         SC(11,-1): "Descent into the cave",
209         SC(11,-2): "The mine",
210         SC(11,-3): "The bottom of mine",
211         SC(10,-3): "In shallow water",
212         SC( 9,-3): "In shallow water",
213         SC( 8,-3): "Afloat",
214         SC( 8,-4): "In the deep",
215         SC( 8,-5): "Dangerous deep",
216         SC( 8,-6): "Under thich layer of water",
217         SC( 8,-7): "Before entrance into the deep cave",
218         SC( 9,-7): "Lair of deep-sea dweller",
219         SC( 8,-8): "And can not see the bottom",
220         SC(12,-3): "Corridor in the deep of volcano",
221         SC(13,-3): "Corridor",
222         SC(14,-3): "Breakage",
223         SC(14,-4): "Fork",
224         SC(15,-4): "Blockage",
225         SC(14,-5): "It would seem the bottom",
226         SC(13,-5): "Again breakage",
227         SC(13,-6): "At entrance to the cave",
228         SC(12,-6): "Lair of shallow habitats",
229         SC(13,-7): "On the bottom ov volcano",
230         SC(14,-7): "At entrance to the castle of evil wizard",
231         SC(15,-7): "Travel gallery of Dizzy",
232         SC(15,-8): "Travel gallery of Dizzy",
233         SC(15,-9): "Aquarium and... Fire",
234         SC(16,-9): "Evil wizard Zaks",
235     ];
236 
237     screen_names_ru =
238     [
239         SC(-1,0): "Вход в пещеру",
240         SC(0, 0): "Место посадки",
241         SC(1, 0): "Пещера сияющего дерева",
242         SC(1, 2): "Пещера",
243         SC(1, 4): "Пещера",
244         SC(2, 0): "Долина смерти",
245         SC(3, 0): "Долина смерти",
246         SC(4, 0): "Марсианский колодец",
247         SC(5, 0): "Под открытым небом Марса",
248         SC(6, 0): "Вход в пещеру потухшего вулкана",
249         SC(7, 0): "В пещере",
250         SC(8, 0): "В пещере",
251         SC(9, 0): "Первый марсианин",
252         SC(10,0): "Усадьба агронома",
253         SC(10,2): "Сарай агронома",
254         SC(10,4): "Будка",
255         SC(11,0): "Сад",
256         SC(12,0): "Вход в секретную лабораторию",
257         SC(13,0): "Инженер",
258         SC(14,0): "Жерло вулкана",
259         SC(14,-1): "Жерло вулкана",
260         SC(15,0): "Химическая лаборатория",
261         SC(16,0): "Пещерный коридор",
262         SC(17,0): "Коридор пещерный",
263         SC(18,0): "Выход из пещеры вулкана",
264         SC(19,0): "Стены замка",
265         SC(19,1): "Стены замка",
266         SC(11,-1): "Спуск в пещеру",
267         SC(11,-2): "Шахта",
268         SC(11,-3): "Дно шахты",
269         SC(10,-3): "На мелководье",
270         SC( 9,-3): "На мелководье",
271         SC( 8,-3): "На поверхности",
272         SC( 8,-4): "В глубине",
273         SC( 8,-5): "Опасная глубина",
274         SC( 8,-6): "Под толстым слоем воды",
275         SC( 8,-7): "У входа в глубинную пещеру",
276         SC( 9,-7): "Логово глубоководного обитателя",
277         SC( 8,-8): "И не видно дна",
278         SC(12,-3): "Коридор в глубине вулкана",
279         SC(13,-3): "Коридор",
280         SC(14,-3): "Обрыв",
281         SC(14,-4): "Развилка",
282         SC(15,-4): "Завал",
283         SC(14,-5): "Казалось бы дно",
284         SC(13,-5): "Снова обрыв",
285         SC(13,-6): "У входа в пещеру",
286         SC(12,-6): "Логово мелководных обитателей",
287         SC(13,-7): "На дне вулкана",
288         SC(14,-7): "У входа в замок злого волшебника",
289         SC(15,-7): "Галерея путешествий Диззи",
290         SC(15,-8): "Галерея путешествий Диззи",
291         SC(15,-9): "Аквариум и... Огонь",
292         SC(16,-9): "Злой волшебник - Закс",
293     ];
294 }
295 
296 bool in_the_castle(Item item)
297 {
298     return item.inventory ||
299         item.x >= (15*30.0 - 15.0) &&
300         item.y <= (-7*17.0 + 8.5);
301 }
302 
303 class DizzyOmega:MainGameObject
304 {
305     const (ObjFile)*[10] energy_star;
306     Item[] items;
307     size_t[] inventory;
308     int max_items = 3;
309     GLuint[string] textures;
310     Star[] stars;
311     Tree[] trees;
312     StaticGameObject[] animations;
313     Dialogs dialogs;
314     Star star0;
315     Star star1;
316     Item blanket;
317     Item branch;
318     Item player;
319     Item rope;
320     Item baloon;
321     Item stunning_drink;
322     Item bottle;
323     Item bucket;
324     Item bucket_of_water;
325     Item bucket_of_ice;
326     Item bucket_covered;
327     Item meteorite;
328     Item spade;
329     Item light_branch;
330     Item short_rope;
331     Item stone1;
332     Item stone2;
333     Item stone3;
334     Item bag;
335     Item key;
336     Item pressprot;
337     Item bugs_poison;
338     Item grasshoppers_poison;
339     Item grasshopper_item;
340     Item bird_item;
341     Item bug_item;
342     Item nettle;
343     Item fish_item;
344     Item fish_rod;
345     Item squid_item;
346     Item bucket_with_ground;
347     Item bucket_with_light_water;
348     Item psychotropic_spray;
349     Item whistle;
350     Item umbrella;
351     Item kitchen_knife;
352     Bucket bucket_anim;
353     Rope rope1;
354     Rope rope2;
355     Rope rope3;
356     GroundCastle ground_castle;
357     GroundCave ground_cave;
358     GroundGarden ground_garden;
359     Stones stones;
360     Rotatable door;
361     Rotatable zaks;
362     int rope_state;
363     
364     Mix_Music *energy_minus;
365     Mix_Music *energy_plus;
366     long energy_start_tick = -1;
367     bool music;
368     Mix_Music*[] musics;
369     float[] music_len;
370     string[] music_name;
371     long music_start_tick = -1;
372     int track;
373     
374     //float stopped_music_position;
375     MUSIC_STATE music_state;
376 
377     enum MUSIC_STATE
378     {
379         MUSIC,
380         ENERGY_PLUS,
381         ENERGY_MINUS,
382     }
383 
384     GLuint[SC] screen_lists;
385 
386     enum LANG
387     {
388         EN = 0,
389         RU = 1,
390         MAX= 1,
391     }
392 
393     LANG lang;
394     
395     immutable string[string] names; 
396     immutable string[string] names_ru;
397 
398     string[TEMP_MESSAGES] temp_messages;
399     string[TEMP_MESSAGES] temp_messages_ru;
400     TEMP_MESSAGES temp_message;
401     string temp_message_str;
402     long temp_message_frame_from;
403     long temp_message_frame_to;
404 
405     int reinit_draw;
406     bool[string] done_dialogs;
407 
408     Random rnd;
409 
410     Dizzy the_hero;
411     BagBugAnim bag_bug_anim;
412     Dog dog;
413     Rotatable martian_engineer;
414     Explosure explosure;
415     Grasshopper grasshopper;
416     Bird bird;
417     Bug bug;
418     Fish fish;
419     Squid squid;
420     ThingsSweepAwayZaks things_sweep_away_zaks;
421     Water water3;
422 
423     int dizzy_used_knife_quest_state = -1;
424     int dizzy_throw_branch_quest_state = -1;
425     int dizzy_cuts_rope_quest_state = -1;
426     int dizzy_live_after_explosure_quest_state = -1;
427     int dizzy_water_flowers_state = -1;
428     int wait_meteorite = -1;
429     int wait_meteorite2 = -1;
430 
431     struct BranchQuestVariables {
432         int st;
433         float degree;
434         float x, y;
435         float dx, dy;
436     }
437 
438     Tid sl_tid;
439     
440     BranchQuestVariables branch_quest_variables;
441 
442     this(GlobalState gs)
443     {
444         textures["font"] = load_texture("models/dizzy/font.png", true, 5);
445         
446         toGame(gs);
447         loadingMessage(gs);
448 
449         foreach(model; ["dizzy", "dizzy-cosmonaut", "kitchen-knife", "blanket",
450                         "stone", "bag", "fish-rod", "rocket", "zaks-face",
451                         "light-drop", "drop", "branch", "bug",
452                         "dog", "martian-engineer", "martian-chemist",
453                         "player",
454                         "rope", "before-explosure",
455                         "after-explosure-down", "after-explosure-up",
456                         "bomb", "baloon", "explosure",
457                         "stunning-drink", "bottle",
458                         "umbrella", "bucket", "bucket-of-water",
459                         "bucket-of-ice", "bucket-covered",
460                         "bucket-out-water", "bucket-water",
461                         "meteorite", "spade", "light-branch",
462                         "short-rope",
463                         "oiler", "grenade",
464                         "branch-of-tree-full", "branch-of-tree-cut",
465                         "branch-on-tree",
466                         "stalagmite", "fall-platform-0",
467                         "platform1", "platform2",
468                         "ground-garden", "ground-garden-1", "ground-garden-2",
469                         "ground-garden-3",
470                         "cave-water", "cave-water-2", "cave-water-3",
471                         "aquarium", "door",
472                         "bird", "flame", "bird-item",
473                         "grasshoppers-poison", "bugs-poison",
474                         "key", "pressure-protection",
475                         "dynamite-grand", "nettle",
476                         "lava-bubble", "platform4",
477                         "ground-cave", "ground-cave-1",
478                         "fish-item", "squid-item",
479                         "psychotropic-spray", "whistle",
480                         "zaks", "ground-castle", "ground-castle-1",
481                         "stones-1", "stones-2"])
482         {
483             models[model] = cast(shared) load_objfile(format("models/%s.obj", model));
484         }
485 
486         models["stone1"] = models["stone"];
487         models["stone2"] = models["stone"];
488         models["stone3"] = models["stone"];
489         models["bucket-with-ground"] = models["bucket"];
490         models["bucket-with-light-water"] = models["bucket"];
491         
492         models["solid"] = cast(shared) load_objfile("models/scene-solid.obj");
493         models["water"] = cast(shared) load_objfile("models/scene-01-water.obj");
494         models["clouds"] = cast(shared) load_objfile("models/scene-01-clouds.obj");
495         models["dangers"] = cast(shared) load_objfile("models/scene-dangers.obj");
496         models["temp-solid"] = cast(shared) load_objfile("models/temp-solid.obj");
497     
498         foreach(i; 0..14)
499         {
500             models[format("tree-%02d", i)] = 
501                 cast(shared) load_objfile(format("models/mars-tree-%02d.obj", i));
502         }
503         
504         models["stone-00"] = cast(shared) load_objfile("models/stone-00.obj");
505         models["stone-01"] = cast(shared) load_objfile("models/stone-01.obj");
506         models["stone-02"] = cast(shared) load_objfile("models/stone-02.obj");
507 
508         models["meteorite-01"] = cast(shared) load_objfile("models/meteorite-01.obj");
509         models["meteorite-02"] = cast(shared) load_objfile("models/meteorite-02.obj");
510         models["meteorite-03"] = cast(shared) load_objfile("models/meteorite-03.obj");
511         
512         models["small-stone-00"] = cast(shared) load_objfile("models/small-stone-00.obj");
513         
514         for (int i=0; i < 10; i++)
515         {
516             models["star-"~i.to!(string)] = cast(shared) load_objfile(("models/energy-star-"~i.to!(string)~".obj"));
517         }
518 
519         for (int i=0; i < 5; i++)
520         {
521             models["fish-"~i.to!(string)] = cast(shared) load_objfile(("models/fish-"~i.to!(string)~".obj"));
522         }
523 
524         for (int i=0; i < 11; i++)
525         {
526             models["squid-"~i.to!(string)] = cast(shared) load_objfile(("models/squid-"~i.to!(string)~".obj"));
527         }
528 
529         for (int i=0; i < 4; i++)
530         {
531             models["flame-"~i.to!(string)] = cast(shared) load_objfile(("models/flame-"~i.to!(string)~".obj"));
532         }
533 
534         for (int i=0; i < 6; i++)
535         {
536             models["grasshopper-"~i.to!(string)] = cast(shared) load_objfile(("models/grasshopper-"~i.to!(string)~".obj"));
537         }
538 
539         collision_objects["solid"] = null;
540         scene_to_collision_object (cast(ObjFile*) models["solid"], collision_objects["solid"]);
541         collision_objects["water"] = null;
542         scene_to_collision_object (cast(ObjFile*) models["water"], collision_objects["water"]);
543         collision_objects["clouds"] = null;
544         scene_to_collision_object (cast(ObjFile*) models["clouds"], collision_objects["clouds"]);
545         collision_objects["dangers"] = null;
546         scene_to_collision_object (cast(ObjFile*) models["dangers"], collision_objects["dangers"]);
547         collision_objects["temp-solid"] = null;
548         scene_to_collision_object (cast(ObjFile*) models["temp-solid"], collision_objects["temp-solid"]);
549 
550         models.remove("solid");
551         models.remove("water");
552         models.remove("clouds");
553         models.remove("dangers");
554         models.remove("temp-solid");
555 
556         models["bug-solid"] = cast(shared) load_objfile("models/bug-collisions.obj");
557         collision_objects["bug-solid"] = null;
558         scene_to_collision_object (cast(ObjFile*) models["bug-solid"], collision_objects["bug-solid"]);
559 
560         models["grasshopper-solid"] = cast(shared) load_objfile("models/grasshopper-collisions.obj");
561         collision_objects["grasshopper-solid"] = null;
562         scene_to_collision_object (cast(ObjFile*) models["grasshopper-solid"], collision_objects["grasshopper-solid"]);
563 
564         models["grasshopper-solid-1"] = cast(shared) load_objfile("models/grasshopper-collisions-1.obj");
565         collision_objects["grasshopper-solid-1"] = null;
566         scene_to_collision_object (cast(ObjFile*) models["grasshopper-solid-1"], collision_objects["grasshopper-solid-1"]);
567 
568         models["underground-solid"] = cast(shared) load_objfile("models/underground-collisions.obj");
569         collision_objects["underground-solid"] = null;
570         scene_to_collision_object (cast(ObjFile*) models["underground-solid"], collision_objects["underground-solid"]);
571 
572         collision_objects["solid"]["BranchForBreak"] = collision_objects["temp-solid"]["BranchForBreak"];
573         collision_objects["solid"]["Platform1"] = collision_objects["temp-solid"]["Platform1"];
574         collision_objects["solid"]["Platform2"] = collision_objects["temp-solid"]["Platform2"];
575         collision_objects["solid"]["BeforeExplosure1"] = collision_objects["temp-solid"]["BeforeExplosure1"];
576         collision_objects["solid"]["BeforeExplosure2"] = collision_objects["temp-solid"]["BeforeExplosure2"];
577         collision_objects["solid"]["GroundGarden"] = collision_objects["temp-solid"]["GroundGarden"];
578         collision_objects["solid"]["Stone2"] = collision_objects["temp-solid"]["Stone2"];
579         collision_objects["solid"]["Platform4"] = collision_objects["temp-solid"]["Platform4"];
580         collision_objects["solid"]["Wall1"] = collision_objects["temp-solid"]["Wall1"];
581 
582         items = [kitchen_knife = new Item(this, [93.7, -4.9, 0.0], "kitchen-knife"),
583                  stone1 = new Item(this, [223.1, 2.9, 0.0], "stone1"),
584                  fish_rod = new Item(this, [309.0, 34.5, 3.0], "fish-rod"),
585                  branch = new Item(this, [330.0, 34.0, 0.0], "branch"),
586                  light_branch = new Item(this, [390.0, 34.0, 0.0], "light-branch"),
587                  player = new Item(this, [120.0, 34.0, 0.0], "player"),
588                  rope = new Item(this, [280.0, 34.0, 0.0], "rope"),
589                  baloon = new Item(this, [433.0, -22.0, 0.0], "baloon"),
590                  stunning_drink = new Item(this, [450.0, 34.0, 0.0], "stunning-drink"),
591                  bottle = new Item(this, [450.0, 34.0, 0.0], "bottle"),
592                  umbrella = new Item(this, [511.5, -6.6, -2.6], "umbrella"),
593                  stone2 = new Item(this, [334.6, 34.0, 0.0], "stone2"),
594                  stone3 = new Item(this, [422.0, -98.4, 0.0], "stone3"),
595                  bucket = new Item(this, [280.0, 34.0, 0.0], "bucket"),
596                  bucket_of_water = new Item(this, [280.0, 34.0, 0.0], "bucket-of-water"),
597                  bucket_of_ice = new Item(this, [280.0, 34.0, 0.0], "bucket-of-ice"),
598                  bucket_covered = new Item(this, [280.0, 34.0, 0.0], "bucket-covered"),
599                  bucket_with_ground = new Item(this, [280.0, 34.0, 0.0], "bucket-with-ground"),
600                  bucket_with_light_water = new Item(this, [280.0, 34.0, 0.0], "bucket-with-light-water"),
601                  blanket = new Item(this, [210.7, -6.4, 0.0], "blanket"),
602                  meteorite = new Item(this, [150.0, 34.0, 0.0], "meteorite"),
603                  spade = new Item(this, [390.0, 34.0, 0.0], "spade"),
604                  short_rope = new Item(this, [360.0, 34.0, 0.0], "short-rope"),
605                  new Item(this, [-30.1, -7.3, 0.0], "oiler"),
606                  new Item(this, [-40.6, -2.6, 0.0], "grenade"),
607                  bag = new Item(this, [262.8, -57.5, 0.0], "bag"),
608                  grasshoppers_poison = new Item(this, [392.2, -99.0, 0.0], "grasshoppers-poison"),
609                  bugs_poison = new Item(this, [231.9, -71.9, 0.0], "bugs-poison"),
610                  key = new Item(this, [439.0, -72.7, 0.0], "key"),
611                  pressprot = new Item(this, [465.9, 34.0, 0.0], "pressure-protection"),
612                  new Item(this, [453.2, -116.0, 0.0], "dynamite-grand"),
613                  nettle = new Item(this, [20.5, 33.8, 0.0], "nettle"),
614                  grasshopper_item = new Item(this, [20.5, 80.0, 0.0], "grasshopper-0"),
615                  bird_item = new Item(this, [150.0, 80.0, 0.0], "bird-item"),
616                  bug_item = new Item(this, [150.0, 80.0, 0.0], "bug"),
617                  fish_item = new Item(this, [150.0, 80.0, 0.0], "fish-item"),
618                  squid_item = new Item(this, [150.0, 80.0, 0.0], "squid-item"),
619                  psychotropic_spray = new Item(this, [150.0, 80.0, 0.0], "psychotropic-spray"),
620                  whistle = new Item(this, [150.0, 80.0, 0.0], "whistle"),];
621 
622         stars = [new Star(this, [21.6, -3.0, 0.0]),
623                  new Star(this, [84.3, -3.4, 0.0]),
624                  new Star(this, [189.0, 2.5, 0.0]),
625                  new Star(this, [273.0, 3.0, 0.0]),
626                  new Star(this, [270.0, -5.2, 0.0]),
627                  new Star(this, [295.0, -1.2, 0.0]),
628                  new Star(this, [293.2, 38.4, 3.0]),
629                  new Star(this, [326.5, 2.24, -0.9]),
630                  new Star(this, [357.8, 3.9, 0.9]),
631                  new Star(this, [402.7, -2.3, 0.0]),
632                  star0 = new Star(this, [418.7, 5.2, 0.0]),
633                  new Star(this, [436.0, 5.0, 0.0]),
634                  new Star(this, [466.4, 1.7, 0.0]),
635                  new Star(this, [511.5, -6.6, 0.0]),
636                  new Star(this, [572.8, 1.5, 0.0]),
637                  new Star(this, [277.5, -58.0, 0.0]),
638                  new Star(this, [244.8, -74.8, 0.0]),
639                  new Star(this, [245.5, -124.5, 0.0]),
640                  new Star(this, [242.2, -132.8, 0.0]),
641                  new Star(this, [402.2, -56.9, 0.0]),
642                  new Star(this, [419.8, -54.7, 0.0]),
643                  new Star(this, [427.8, -87.7, 0.0]),
644                  new Star(this, [353.7, -99.3, 0.0]),
645                  new Star(this, [347.3, -108.3, 0.0]),
646                  new Star(this, [460.7, -121.8, 0.0]),
647                  new Star(this, [444.7, -137.8, 0.0]),
648                  new Star(this, [484.7, -158.9, 0.0]),
649                  star1 = new Star(this, [29.9, 34.8, 0.0]),
650                  new Star(this, [22.9, 69.8, 0.0]),];
651 
652         trees = [new Tree(this, 2.7, [4.0, -7.5, 0.7], 0),
653                  new Tree(this, 2.47, [97.7, -2.7, 0.7], 1),
654                  new Tree(this, 4.44, [108.0, -5.5, 2.1], 2),
655                  new Tree(this, 3.0, [114.0, -5.9, 0.9], 3),
656                  new Tree(this, 1.9, [115.0, 0.2, 1.6], 4),
657                  new Tree(this, 1.9, [116.6, 0.3, -1.6], 5),
658                  new Tree(this, 2.54, [119.2, 0.2, 2.1], 6),
659                  new Tree(this, 4.1, [122.0, -6.3, -2.0], 7),
660                  new Tree(this, 3.5, [128.0, -3.1, 1.4], 8),
661                  new Tree(this, 3.2, [137.2, -5.3, 0.7], 9),
662                  new Tree(this, 3.5, [150.0, -4.9, 1.6], 10),
663                  new Tree(this, 3.0, [158.3, -4.5, 1.1], 11),
664                  new Tree(this, 3.3, [169.7, -6.1, 1.6], 12),
665                  new Tree(this, 3.1, [180.0, -6.5, 0.7], 13),
666                  ];
667         
668         the_hero = new Dizzy(this, [-7.0, -7.2, 0.0]);
669 
670         bag_bug_anim = new BagBugAnim(this);
671 
672         rnd = Random(28);
673         
674         animations = [new Stone00(this, the_hero),
675                       new Stone01(this, the_hero),
676                       new Stone02(this, the_hero),
677                       new SkyZaks(this, the_hero),
678                       new Stalagmite(this, the_hero),
679                       new Meteorite(this, the_hero, bird, rnd),
680                       new LightDrop(this),
681                       new Drop(this, 197.4, 2.1, 1.8, -6.2, -1.6, 0),
682                       new Drop(this, 305.5, 8.4, 8.3, 5.1, 3.9, 0),
683                       new Drop(this, 306.8, 8.4, 8.3, 5.6, 3.9, 100),
684                       new Drop(this, 308.2, 8.4, 8.3, 5.6, 3.9, 150),
685                       new Drop(this, 311.3, 8.4, 8.3, 5.6, 3.9, 225),
686                       new Drop(this, 454.8, 0.8, 0.6, -6.3, 1.9, 0),
687                       new Drop(this, 458.9, 0.8, 0.6, -2.0, 1.9, 50),
688                       new Drop(this, 461.9, 0.8, 0.6, -2.0, 1.9, 250),
689                       new Drop(this, 457.3, -2.8, -3.0, -6.3, 1.9, 280),
690                       new Drop(this, 458.9, -2.8, -3.0, -6.3, 1.9, 220),
691                       new Drop(this, 460.6, -2.8, -3.0, -6.3, 1.9, 120),
692                       new Drop(this, 461.6, -2.8, -3.0, -6.3, 1.9, 180),
693                       new Drop(this, 308.6, -48.5, -48.8, -55.2, 2.1, 0),
694                       new Drop(this, 298.0, -48.0, -48.2, -55.2, 2.1, 100),
695                       new Drop(this, 291.7, -48.3, -48.6, -55.2, 2.1, 87),
696                       new Drop(this, 273.5, -46.6, -46.8, -55.2, 2.1, 24),
697                       new Drop(this, 267.0, -48.0, -48.3, -55.2, 2.1, 250),
698                       new Drop(this, 260.4, -50.1, -50.5, -55.2, 2.1, 180),
699                       new FallPlatform(this, the_hero, [247.3, 2.1, 0.0], 0),
700                       bug = new Bug(this, [252.0, -5.6, 0.0], "bug-solid"),
701                       grasshopper = new Grasshopper(this, [20.6, 60.5, 0.0], "grasshopper-solid", "grasshopper-solid-1", the_hero),
702                       dog = new Dog(this, [362.0, -3.5, 0.0], [359.5, -2.4, 3.0], -5.1, 20, 0.5, the_hero),
703                       martian_engineer = new Rotatable(this, [401.8, 2.7, 0.0], 90.0, "martian-engineer"),
704                       new Rotatable(this, [463.2, 1.7, 2.1], 0.0, "martian-chemist"),
705                       new Platform1(this, [418.5, 4.6, 0.0]),
706                       explosure = new Explosure(this, [416.4, -20.7, 0.0], [425.4, -16.7, 0.0], [412.4, -20.5, 0.0], the_hero),
707                       bucket_anim = new Bucket(this),
708                       ground_garden = new GroundGarden(this),
709                       stones = new Stones(this),
710                       bird = new Bird(this, [318.7, -36.2, 0.0], 332.7, the_hero),
711                       new Fish(this, [232.8, -85.9, 0.0], 232.8, 240.8, 1.0, 1.0),
712                       new Fish(this, [348.4, -106.0, 0.0], 348.4, 366.9, 0.5, 1.0),
713                       new Fish(this, [352.0, -106.0, 0.0], 348.4, 366.9, 0.7, 0.8),
714                       fish = new Fish(this, [366.9, -106.0, 0.0], 348.4, 366.9, 0.4, 1.2),
715                       new Fish(this, [459.0, -149.5, 4.0], 450.0, 468.0, 1.5, 0.25),
716                       squid = new Squid(this, [276.0, -113.0, 0.0], -120.0),
717                       new Water(this, "cave-water", -55.5),
718                       new Water(this, "cave-water-2", -106.01),
719                       water3 = new Water(this, "cave-water-3", -160.0),
720                       new Statical(this, "aquarium"),
721                       door = new Rotatable(this, [17.3, 2.0, 2.0], 0.0, "door"),
722                       new Flame(this, [458.5, -157.3, 1.0], 0),
723                       new Flame(this, [451.8, -157.3, 1.0], 2),
724                       new Lava(this, [422.3, -125.4, -2.5], [429.3, -124.4, 2.5], rnd),
725                       new Platform4(this, [29.6, 34.4, 0.0]),
726                       ground_cave = new GroundCave(this),
727                       ground_castle = new GroundCastle(this),
728                       zaks = new Rotatable(this, [489.0, -159.1, 0.0], 0.0, "zaks"),
729                       things_sweep_away_zaks = new ThingsSweepAwayZaks(this),
730                       ];
731 
732         rope1 = new Rope(root, [418.1, 1.3, 0.7], [416.9, 1.3, 0.0], -13.0, 30, 0.5, 3);
733         rope2 = new Rope(root, [245.0, 2.2, 0.7], [246.2, 2.2, 0.0], -5.0, 7, 0.5, 3);
734         rope3 = new Rope(root, [331.2, -13.7, 0.7], [333.0, -13.7, 0.0], -53.1, 70, 0.5, 3);
735         
736         textures["live"] = load_texture("models/dizzy/dizzy-live.png");
737         textures["energy"] = load_texture("models/dizzy/energy.png");
738 
739         names =
740         [
741             "kitchen-knife": "Kitchen Knife",
742             "blanket": "Quilted Blanket",
743             "stone1": "Stone",
744             "stone2": "Stone",
745             "stone3": "Stone",
746             "fish-rod": "Fish Rod",
747             "branch": "Branch",
748             "light-branch": "Light Branch",
749             "player": "Player",
750             "rope": "Rope",
751             "baloon": "Baloon",
752             "stunning-drink": "Stunning drink",
753             "bottle": "Bottle",
754             "umbrella": "Umbrella",
755             "bucket": "Bucket",
756             "bucket-of-water": "Bucket Of Water",
757             "bucket-of-ice": "Bucket Of Ice",
758             "bucket-covered": "Covered Bucket of Water",
759             "bucket-with-ground": "Bucket with ground",
760             "bucket-with-light-water": "Bucket with light water",
761             "meteorite": "Meteorite",
762             "spade": "Spade",
763             "short-rope": "Short Rope",
764             "oiler": "Oiler",
765             "grenade": "Hand Grenade",
766             "grasshoppers-poison": "Grasshopper Poison",
767             "bugs-poison": "Bug Poison",
768             "key": "Key",
769             "pressure-protection": "Pressure Protection",
770             "dynamite-grand": "Dynamite Grand",
771             "nettle": "Nettle",
772             "grasshopper-0": "Grasshopper",
773             "bird-item": "Bird",
774             "bug": "Bug",
775             "fish-item": "Fish",
776             "squid-item": "Squid",
777             "psychotropic-spray": "Psychotropic Spray",
778             "whistle": "Whistle",
779         ];
780 
781         names_ru =
782         [
783             "kitchen-knife": "Кухонный нож",
784             "blanket": "Ватное Одеяло",
785             "stone1": "Камень",
786             "stone2": "Камень",
787             "stone3": "Камень",
788             "fish-rod": "Удочка",
789             "branch": "Ветка",
790             "light-branch": "Сияющая ветка",
791             "player": "Плеер",
792             "rope": "Верёвка",
793             "baloon": "Воздушный шар",
794             "stunning-drink": "Напиток \"Сногсшибающий\"",
795             "bottle": "Бутылка",
796             "umbrella": "Зонт",
797             "bucket": "Ведро",
798             "bucket-of-water": "Ведро воды",
799             "bucket-of-ice": "Ведро льда",
800             "bucket-covered": "Накрытое Ведро с Водой",
801             "bucket-with-ground": "Ведро с землёй",
802             "bucket-with-light-water": "Ведро с сияющей водой",
803             "meteorite": "Метеорит",
804             "spade": "Лопата",
805             "short-rope": "Короткая Верёвка",
806             "oiler": "Маслёнка",
807             "grenade": "Ручная Граната",
808             "grasshoppers-poison": "Отрава для кузнечиков",
809             "bugs-poison": "Отрава для жуков",
810             "key": "Ключ",
811             "pressure-protection": "Защита от давления",
812             "dynamite-grand": "Динамит большой",
813             "nettle": "Сачок",
814             "grasshopper-0": "Кузнечик",
815             "bird-item": "Птичка",
816             "bug": "Жук",
817             "fish-item": "Рыба",
818             "squid-item": "Кальмар",
819             "psychotropic-spray": "Психотропный Препарат",
820             "whistle": "Свисток",
821         ];
822 
823         temp_messages =
824         [
825             TEMP_MESSAGES.CANT_SAVE_IN_THE_MOVING: "Can't save in the moving",
826             TEMP_MESSAGES.CANT_SAVE_DURING_THE_QUEST: "Can't save during the quest",
827             TEMP_MESSAGES.SAVED: "Saved",
828             TEMP_MESSAGES.NEGATIVE_LIVES: "Negative amount of lives",
829             TEMP_MESSAGES.PLAYS: "Plays",
830         ];
831 
832         temp_messages_ru =
833         [
834             TEMP_MESSAGES.CANT_SAVE_IN_THE_MOVING: "Не могу сохранить в движении",
835             TEMP_MESSAGES.CANT_SAVE_DURING_THE_QUEST: "Не могу сохранить во время квеста",
836             TEMP_MESSAGES.SAVED: "Сохранено",
837             TEMP_MESSAGES.NEGATIVE_LIVES: "Отрицательное число жизней",
838             TEMP_MESSAGES.PLAYS: "Звучит",
839         ];
840 
841         dialogs = new Dialogs(this);
842 
843         /*if (scene) {
844             get_bounding_box(scene, &scene_min, &scene_max);
845             scene_center.x = (scene_min.x + scene_max.x) / 2.0f;
846             scene_center.y = (scene_min.y + scene_max.y) / 2.0f;
847             scene_center.z = (scene_min.z + scene_max.z) / 2.0f;
848         }
849         else
850             throw new Exception(format("Error while aiImportFile"));*/
851 
852         energy_minus = Mix_LoadMUS("sounds/energy-minus.ogg");
853         if(!energy_minus) {
854             writefln("Mix_LoadMUS 'sounds/energy_minus.ogg': %s", Mix_GetError().to!(string)());
855         }
856 
857         energy_plus = Mix_LoadMUS("sounds/energy-plus.ogg");
858         if(!energy_plus) {
859             writefln("Mix_LoadMUS 'sounds/energy_plus.ogg': %s", Mix_GetError().to!(string)());
860         }
861 
862         musics = [null, null, null, null, null];
863         music_len = [0.0f, 0.0f, 0.0f, 0.0f, 0.0f];
864         music_name = ["", "", "", "", ""];
865 
866         musics[0] = Mix_LoadMUS("music/GraveBeholders_TheSadnessOfMyWorld.ogg");
867         if(!musics[0]) {
868             writefln("Mix_LoadMUS 'music/GraveBeholders_TheSadnessOfMyWorld.ogg': %s", Mix_GetError().to!(string)());
869         }
870         music_len[0] = 632.0;
871         music_name[0] = "Grave Beholders: The Sadness Of My World";
872 
873         musics[1] = Mix_LoadMUS("music/SergeySirotin_Magic.ogg");
874         if(!musics[1]) {
875             writefln("Mix_LoadMUS 'music/SergeySirotin_Magic.ogg': %s", Mix_GetError().to!(string)());
876         }
877         music_len[1] = 232.6;
878         music_name[1] = "Sergey Sirotin: Magic";
879 
880         musics[2] = Mix_LoadMUS("music/OlegGurtovoy_FreeFlight.ogg");
881         if(!musics[2]) {
882             writefln("Mix_LoadMUS 'music/OlegGurtovoy_FreeFlight.ogg': %s", Mix_GetError().to!(string)());
883         }
884         music_len[2] = 234.2;
885         music_name[2] = "Oleg Gurtovoy: Free Flight";
886 
887         musics[3] = Mix_LoadMUS("music/PaulWhite_ViolinQuartet.ogg");
888         if(!musics[3]) {
889             writefln("Mix_LoadMUS 'music/PaulWhite_ViolinQuartet.ogg': %s", Mix_GetError().to!(string)());
890         }
891         music_len[3] = 206.5;
892         music_name[3] = "Paul White: Violin Quartet";
893 
894         musics[4] = Mix_LoadMUS("music/SergeySirotin_NightCity.ogg");
895         if(!musics[4]) {
896             writefln("Mix_LoadMUS 'music/SergeySirotin_NightCity.ogg': %s", Mix_GetError().to!(string)());
897         }
898         music_len[4] = 249.8;
899         music_name[4] = "Sergey Sirotin: Night City";
900 
901         music_start_tick = cast(long)SDL_GetTicks();
902 
903         music = true;
904 
905         super(this);
906 
907         gs.syncTime();
908     }
909 
910     ~this()
911     {
912         /*foreach (model; models)
913         {
914             aiReleaseImport(model);
915         }
916         aiDetachAllLogStreams();*/
917     }
918 
919     void loadingMessage(GlobalState gs)
920     {
921         glClearColor(0.0, 0.0, 0.0, 1.0);
922         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
923         glDisable(GL_LIGHTING);
924         
925         glMatrixMode(GL_MODELVIEW);
926         glLoadIdentity();
927         
928         float tmp = aspectRatio/15.0;
929         glScalef(tmp, tmp, tmp);
930 
931         glRotatef(15.0+params[7]*10,-1,1,0);
932         glRotatef(1.0443,0,0,1);
933         glScalef(0.75, 0.75, 0.75);
934         glTranslatef(2.2, 2.0, 0.0);
935 
936         glPushMatrix();
937         glTranslatef(-5.0, 1.0, 0.0);
938 
939         glBindTexture(GL_TEXTURE_2D, textures["font"]);
940         glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
941         glEnable(GL_COLOR_MATERIAL);
942         glColor4f(1.0, 1.0, 0.0, 1.0);
943         print_text("Loading...\n"~
944                    "Please wait");
945         glPopMatrix();
946         
947         glScalef(0.5, 0.5, 0.5);
948         glTranslatef(-34.0, -14.0, 0.0);
949         glColor4f(0.75, 0.75, 0.75, 1.0);
950         print_text("   \"Dizzy\", \"The Yolkfolk\" and all related characters and titles\n"~ 
951                    "are trademarks of Oliver Twins Limited and The Codemasters Software\n"~
952                    "                            Company Limited.");
953         glEnable(GL_LIGHTING);
954         
955         SDL_RenderPresent(gs.renderer);
956     }
957 
958     double aspectRatio;
959 
960     void initViewPort(int w, int h)
961     {
962         aspectRatio = cast(double) w / h;
963 
964         glMatrixMode(GL_PROJECTION);
965         glLoadIdentity();
966 
967         GLfloat windowWidth; GLfloat windowHeight;
968         if (w <= h)
969         {
970             windowWidth = 1;
971             windowHeight = 1/aspectRatio;
972             glOrtho(-windowWidth, windowWidth, -windowHeight, windowHeight, 100.0, -100.0);
973         }
974         else
975         {
976             windowWidth = 1*aspectRatio;
977             windowHeight = 1;
978             glOrtho(-windowWidth, windowWidth, -windowHeight, windowHeight, 100.0, -100.0);
979         }
980 
981         glViewport(0, 0, w, h);
982 
983         //Initialize Modelview Matrix
984         glMatrixMode( GL_MODELVIEW );
985         glLoadIdentity();
986     }
987 
988     void toGame(GlobalState gs)
989     {
990         if (sl_tid == Tid.init)
991         {
992             sl_tid = spawn(&scene_loader, &screens,
993                 &screen_names,
994                 cast(int) round(scrx/30.0),
995                 cast(int) round(scry/17.0),
996                 5, thisTid);
997         }
998         
999         SDL_SetRenderTarget(gs.renderer, null);
1000         initViewPort(gs.screen.w+32*6, gs.screen.h);
1001         glEnable(GL_DEPTH_TEST);
1002         glEnable(GL_CULL_FACE);
1003         glEnable(GL_TEXTURE_2D);
1004         glUseProgram(0);
1005 
1006         if (music)
1007         {
1008             if (Mix_PlayMusic(musics[track], -1) == -1)
1009             {
1010                 writefln("Mix_PlayMusic: %s",
1011                     Mix_GetError().to!(string)());
1012             }
1013     
1014             if(Mix_SetMusicPosition((
1015                 (SDL_GetTicks() - music_start_tick)/1000.0)%
1016                 music_len[track]) == -1) {
1017                 writefln("Mix_SetMusicPosition: %s\n",
1018                     Mix_GetError().to!(string)());
1019             }
1020             
1021             print_message(TEMP_MESSAGES.PLAYS, " "~music_name[track]);       
1022         }
1023     }
1024 
1025     void fromGame(GlobalState gs)
1026     {
1027         if (sl_tid != Tid.init)
1028         {
1029             sl_tid.send(true);
1030             sl_tid = Tid.init;
1031         }
1032         
1033         glDisable(GL_DEPTH_TEST);
1034         glDisable(GL_CULL_FACE);
1035         glMatrixMode(GL_MODELVIEW);
1036         glLoadIdentity();
1037 
1038         Mix_HaltMusic();
1039         Mix_HaltChannel(-1);
1040     }
1041 
1042     float[8] params = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
1043     bool p_changed;
1044 
1045     void parametrizer()
1046     {
1047         int i;
1048         if (keys & CTRL_KEY)
1049             i += 1;
1050         if (keys & SHIFT_KEY)
1051             i += 2;        
1052         
1053         if (keys & LEFT_KEY)
1054             params[i*2+0] -= 0.01;
1055         if (keys & RIGHT_KEY)
1056             params[i*2+0] += 0.01;
1057             
1058         if (keys & DOWN_KEY)
1059             params[i*2+1] -= 0.01;
1060         if (keys & UP_KEY)
1061             params[i*2+1] += 0.01;
1062 
1063         if (keys & (LEFT_KEY|RIGHT_KEY|DOWN_KEY|UP_KEY))
1064         {
1065             p_changed = true;
1066         }
1067         else
1068         {
1069             if (p_changed) writefln("params = %s", params);
1070             p_changed = false;
1071         }
1072     }
1073 
1074     int draw_tree;
1075 
1076     bool all_items_in_the_castle()
1077     {
1078         Item[] items = [kitchen_knife, player, baloon, umbrella, stone1, stone2, bucket, blanket, spade, whistle];
1079         foreach (item; items)
1080         {
1081             if (!item.in_the_castle) return false;
1082         }
1083         return true;
1084     }
1085 
1086     override void draw(GlobalState gs)
1087     {
1088         float tmp;
1089 
1090         if (reinit_draw > 0)
1091         {
1092             toGame(gs);
1093             reinit_draw--;
1094         }
1095 
1096         glClearColor(0.0, 0.0, 0.0, 1.0);
1097         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1098 
1099         glMatrixMode(GL_MODELVIEW);
1100         glLoadIdentity();
1101 
1102         glRotatef(15.0+params[7]*10,-1,1,0);
1103         glRotatef(1.0443,0,0,1);
1104 
1105         tmp = aspectRatio/15.0;
1106         glScalef(tmp, tmp, tmp);
1107 
1108         bool star_found;
1109         foreach(star; stars)
1110         {
1111             star_found = star.set_light(gs);
1112             if (star_found) break;
1113         }
1114         
1115         if (!star_found)
1116             glDisable(GL_LIGHT1);
1117 
1118         // Light Tree
1119         if (scrx == 0.0 && scry == 0.0)
1120         {
1121             glEnable(GL_LIGHT2);
1122             glLightfv(GL_LIGHT2, GL_POSITION, [11.8f, -5.8f, 1.0f, 1.0f].ptr);
1123             glLightfv(GL_LIGHT2, GL_DIFFUSE,
1124                 [0.0f,
1125                  cast(float)(0.065f + 0.03*sin(cast(float)frame/50)),
1126                  cast(float)(0.065f + 0.03*cos(cast(float)frame/50)),
1127                  1.0f].ptr);
1128             glLighti(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, 1);
1129         }
1130         else
1131         {
1132             glDisable(GL_LIGHT2);
1133         }
1134 
1135         SC sc = SC(cast(int)round(scrx/30), cast(int)round(scry/17));
1136 
1137         /* Underground */
1138         if (sc.y < 0 && sc.x >= 8 && sc.x <= 14 &&
1139             !(sc.x == 14 && sc.y == -1) || sc.x == 15 && sc.y == -4)
1140         {
1141             if (sc.y == -1)
1142             {
1143                 glEnable(GL_LIGHT0);
1144                 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, [0.0f, 0.0f, 0.0f, 1.0f].ptr);
1145     
1146                 glLightfv(GL_LIGHT0, GL_POSITION, [0f, 15f, 5.0f, 1.0f].ptr);
1147                 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, [0.0f, 0.5f, -0.1f].ptr);
1148                 glLighti(GL_LIGHT0, GL_SPOT_EXPONENT, 90);
1149                 glLighti(GL_LIGHT0, GL_SPOT_CUTOFF, 180);
1150                 glLighti(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0);
1151                 glLighti(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 3);
1152             }
1153             else
1154             {
1155                 glDisable(GL_LIGHT0);
1156             }
1157         }
1158         else
1159         {
1160             glEnable(GL_LIGHT0);
1161             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, [0.2f, 0.2f, 0.2f, 1.0f].ptr);
1162             glLightfv(GL_LIGHT0, GL_POSITION, [-75f, -75f, 150.0f, 1.0f].ptr);
1163             glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, [0.5f, 0.5f, -1.0f].ptr);
1164             glLighti(GL_LIGHT0, GL_SPOT_EXPONENT, 64);
1165             glLighti(GL_LIGHT0, GL_SPOT_CUTOFF, 90);
1166             glLighti(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1);
1167             glLighti(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0);
1168         }
1169 
1170         //Sky
1171         glEnable(GL_COLOR_MATERIAL);
1172         glDisable(GL_LIGHTING);
1173         glBindTexture(GL_TEXTURE_2D, 0);
1174         glPushMatrix();
1175         glTranslatef(-2.0, -2.0, 0.0);
1176         glBegin(GL_POLYGON);
1177         glColor4f(0.965, 0.665, 0.644, 1.0);
1178         glVertex3f(16.0, 16.0/aspectRatio, 10.0);
1179         glVertex3f(-16.0, 16.0/aspectRatio, 10.0);
1180         glColor4f(1.000, 0.807, 0.617, 1.0);
1181         glVertex3f(-16.0, -16.0/aspectRatio, 10.0);
1182         glVertex3f(16.0, -16.0/aspectRatio, 10.0);
1183         glEnd();
1184         glPopMatrix();
1185         glColor4f(1.0, 1.0, 1.0, 1.0);
1186         glDisable(GL_COLOR_MATERIAL);
1187 
1188         glPushMatrix();
1189         glTranslatef(-scrx, -scry, 0.0);
1190 
1191         /* Underground */
1192         if (sc.y < 0 && sc.x >= 8 && sc.x <= 14 &&
1193             !(sc.x == 14 && sc.y == -1) || sc.x == 15 && sc.y == -4)
1194         {
1195             glEnable(GL_LIGHT2);
1196             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, [0.0f, 0.0f, 0.0f, 1.0f].ptr);
1197             glLightfv(GL_LIGHT2, GL_DIFFUSE,
1198                 [0.3f,
1199                  cast(float)(0.365f + 0.15*sin(cast(float)frame/50)),
1200                  cast(float)(0.365f + 0.15*cos(cast(float)frame/50)),
1201                  1.0f].ptr);
1202             glLightf(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, 0.25f);
1203 
1204             if (light_branch.inventory)
1205             {
1206                 glLightfv(GL_LIGHT2, GL_POSITION, [the_hero.x, the_hero.y+1.5f, the_hero.z+8.0f, 1.0f].ptr);
1207             }
1208             else
1209             {
1210                 glLightfv(GL_LIGHT2, GL_POSITION, [light_branch.x, light_branch.y+.5f, light_branch.z+8.0f, 1.0f].ptr);
1211             }
1212         }
1213 
1214         the_hero.draw(gs);
1215 
1216         foreach(star; stars)
1217         {
1218             star.draw(gs);
1219         }
1220 
1221         stars[0].force_draw(gs);
1222 
1223         /*if (the_hero.show_sensors)
1224             recursive_render(gs, models["solid"]);
1225         else*/
1226         {
1227             if (sc !in screen_lists)
1228             {
1229                 if (sc !in screens)
1230                 {
1231                     loadingMessage(gs);
1232                     return;
1233                 }
1234                 
1235                 screen_lists[sc] = glGenLists(1);
1236                 if (screen_lists[sc] <= 0)
1237                     throw new Exception(format("Error while glGenLists: %s", screen_lists[sc]));
1238                 glNewList(screen_lists[sc], GL_COMPILE_AND_EXECUTE);
1239                 recursive_render(gs, screens[sc], null, null, true, sc.y >= 0);
1240                 glEndList();
1241     
1242                 screens[sc] = null;
1243     
1244                 foreach(scc; screen_lists.keys())
1245                 {
1246                     if (scc !in screens)
1247                     {
1248                         glDeleteLists(screen_lists[scc], 1);
1249                         screen_lists.remove(scc);
1250                     }
1251                 }
1252     
1253                 //writefln("%s", GC.stats());
1254             }
1255             else
1256             {
1257                 glCallList(screen_lists[sc]);
1258             }
1259         }
1260 
1261         foreach(tree; trees)
1262         {
1263             tree.draw(gs);
1264         }
1265 
1266         foreach (ref item; items)
1267         {
1268             item.draw(gs);
1269         }
1270 
1271         foreach(anim; animations)
1272         {
1273             anim.draw(gs);
1274         }
1275         
1276         bag_bug_anim.draw(gs);
1277 
1278         if (dizzy_used_knife_quest_state <= 0)
1279         {
1280             glPushMatrix();
1281             glTranslatef(331.78, -3.85, 4.0);
1282             recursive_render(gs, models["branch-of-tree-full"]);
1283             glPopMatrix();
1284         }
1285         else
1286         {
1287             glPushMatrix();
1288             glTranslatef(331.78, -3.85, 4.0);
1289             recursive_render(gs, models["branch-of-tree-cut"]);
1290             glPopMatrix();
1291 
1292             float f = the_hero.frame;
1293 
1294             if (dizzy_used_knife_quest_state == 1 && f < 100.0)
1295             {
1296                 glPushMatrix();
1297                 glTranslatef(326.40, 2.01 - 8.0*f/100.0, -0.50);
1298                 glRotatef(f*8.0, 0.0, 0.0, 1.0);
1299                 recursive_render(gs, models["branch-on-tree"]);
1300                 glPopMatrix();
1301             }
1302             else if (dizzy_used_knife_quest_state <= 2)
1303             {
1304                 glPushMatrix();
1305                 glTranslatef(326.40, -6.0, -0.50);
1306                 glRotatef(800.0, 0.0, 0.0, 1.0);
1307                 recursive_render(gs, models["branch-on-tree"]);
1308                 glPopMatrix();
1309             }
1310         }
1311 
1312         if (dizzy_throw_branch_quest_state == 1 || dizzy_throw_branch_quest_state == 2)
1313         {
1314             glPushMatrix();
1315 
1316             auto b = &branch_quest_variables;
1317 
1318             glTranslatef(b.x, b.y, 0.0);
1319     
1320             glTranslatef(1.5, 2.5, 0.0);
1321             glRotatef(b.degree,0,0,1);
1322             glTranslatef(-1.5, -2.5, 0.0);
1323     
1324             glRotatef(-90,0,1,0);
1325     
1326             glTranslatef(0.0, 1.9, 0.0);
1327             glRotatef(90.0, 1.0, 0.0, 0.0);
1328             glTranslatef(0.0, -1.9, 0.0);
1329             glTranslatef(-0.9, 0.5, -0.1);
1330     
1331             glRotatef(55.0, 0.0, 1.0, 0.0);
1332             glRotatef(-60.0, 0.0, 0.0, 1.0);
1333             glScalef(0.5, 0.5, 0.5);
1334 
1335             recursive_render(gs, models["branch"]);
1336             
1337             glPopMatrix();
1338         }
1339         else if (dizzy_throw_branch_quest_state == 3 || dizzy_throw_branch_quest_state == 4)
1340         {
1341             glPushMatrix();
1342             
1343             auto b = &branch_quest_variables;
1344 
1345             float f = (dog.frame*4)%240;
1346             float translate = 0.0;
1347             
1348             if (f < 120.0)
1349                 translate = 0.2 - 0.4*f/120.0;
1350             else if (f < 240.0)
1351                 translate = -0.2 + 0.4*(f - 120.0)/120.0;
1352 
1353             glTranslatef(dog.x, dog.y + b.y + translate, dog.z);
1354 
1355             glTranslatef(-3.0, -0.2, 0.3);
1356             glRotatef(-61.5, 0.430, -0.875, 0.224);
1357             glScalef(0.5, 0.5, 0.5);
1358 
1359             recursive_render(gs, models["branch"]);
1360 
1361             glPopMatrix();
1362         }
1363 
1364         if (scrx == 0.0 && scry == 0.0)
1365         {
1366             glPushMatrix();
1367             glTranslatef(-11.8, -6.4, 3.2);
1368             recursive_render(gs, models["rocket"]);
1369             glPopMatrix();
1370         }
1371 
1372         switch(rope_state)
1373         {
1374             case 0:
1375                 break;
1376             case 1:
1377                 rope1.draw(gs);
1378                 break;
1379             case 2:
1380                 rope2.draw(gs);
1381                 break;
1382             case 3:
1383                 rope3.draw(gs);
1384                 break;
1385             default:
1386                 assert(0);
1387         }
1388         
1389         glPopMatrix();
1390 
1391         //Indicators
1392         glDisable(GL_LIGHTING);
1393 
1394         glScalef(0.75, 0.75, 0.75);
1395 
1396         glPushMatrix();
1397         glTranslatef(2.2, 2.0, 0.0);
1398 
1399         if ((the_hero.y - scry) > 4.0)
1400             indicators_down = true;
1401 
1402         if ((the_hero.y - scry) < -4.0)
1403             indicators_down = false;
1404 
1405         float iy = 21.0/aspectRatio-2.0;
1406         if (indicators_down)
1407             iy = -21.0/aspectRatio+1.0;
1408         
1409         glBindTexture(GL_TEXTURE_2D, textures["live"]);
1410 
1411         glBegin(GL_POLYGON);
1412         glTexCoord2f(0.0, 0.0);
1413         glVertex3f(-20.0, iy+1.0, -10.0);
1414         glTexCoord2f(0.0, 1.0);
1415         glVertex3f(-20.0, iy, -10.0);
1416         glTexCoord2f(the_hero.lives >=0 ? the_hero.lives : 1, 1.0);
1417         glVertex3f(-20.0 + (the_hero.lives >=0 ? the_hero.lives : 1), iy, -10.0);
1418         glTexCoord2f(the_hero.lives >=0 ? the_hero.lives : 1, 0.0);
1419         glVertex3f(-20.0 + (the_hero.lives >=0 ? the_hero.lives : 1), iy+1.0, -10.0);
1420         glEnd();
1421 
1422         glBindTexture(GL_TEXTURE_2D, textures["energy"]);
1423         glBegin(GL_POLYGON);
1424         glTexCoord2f(0.0, 0.0);
1425         glVertex3f(-16.0, iy+1.0, -10.0);
1426         glTexCoord2f(0.0, 1.0);
1427         glVertex3f(-16.0, iy, -10.0);
1428         glTexCoord2f(energy/100.0, 1.0);
1429         glVertex3f(-16.0 + 8.0*energy/100.0, iy, -10.0);
1430         glTexCoord2f(energy/100.0, 0.0);
1431         glVertex3f(-16.0 + 8.0*energy/100.0, iy+1.0, -10.0);
1432         glEnd();
1433 
1434         int scrX = cast(int) round(scrx/30);
1435         int scrY = cast(int) round(scry/17);
1436 
1437         glPushMatrix();
1438         glBindTexture(GL_TEXTURE_2D, textures["font"]);
1439         glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR);
1440         glEnable(GL_COLOR_MATERIAL);
1441         if (the_hero.lives < 0)
1442         {
1443             glPushMatrix();
1444             glTranslatef(-19.0, iy+1.0, 0.0);
1445             glColor4f(1.0, 1.0, 0.0, 1.0);
1446             print_text(format("%2d", the_hero.lives));
1447             glPopMatrix();
1448         }
1449         glTranslatef(-7.0, iy+1.0, 0.0);
1450         glColor4f(1.0, 1.0, 0.0, 1.0);
1451         print_text(format("%02d", num_stars));
1452         glTranslatef(3.0, 0.0, 0.0);
1453         glColor4f(1.0, 1.0, 1.0, 1.0);
1454         string screen_name;
1455         if ((SC(scrX, scrY) in screen_names))
1456         {
1457             final switch(lang)
1458             {
1459                 case LANG.EN:
1460                     screen_name = screen_names[SC(scrX, scrY)];
1461                     break;
1462                     
1463                 case LANG.RU:
1464                     screen_name = screen_names_ru[SC(scrX, scrY)];
1465                     break;
1466             }
1467         }
1468         print_text(screen_name);
1469 
1470         /*glTranslatef(-8.0, -2.0, 0.0);
1471         print_text(format("FPS %.02f",
1472             gs.fps_frames*1000.0/gs.fps_time));*/
1473         
1474         glPopMatrix();
1475 
1476         draw_temp_message();
1477 
1478         glDisable(GL_COLOR_MATERIAL);
1479         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1480         
1481         dialogs.draw(gs);
1482         glPopMatrix();
1483     }
1484 
1485     void draw_temp_message()
1486     {
1487         if (frame < temp_message_frame_from ||
1488             frame > temp_message_frame_to) return;
1489             
1490         float f = frame - temp_message_frame_from;
1491         glPushMatrix();
1492         
1493         string msg;
1494         final switch (lang)
1495         {
1496             case LANG.EN:
1497                 msg = temp_messages[temp_message] ~ temp_message_str;
1498                 break;
1499             case LANG.RU:
1500                 msg = temp_messages_ru[temp_message] ~ temp_message_str;
1501                 break;
1502         }
1503 
1504         if (temp_message == TEMP_MESSAGES.PLAYS)
1505         {
1506             glScalef(0.5, 0.5, 0.5);
1507             glTranslatef(0.0, -10.0, 0.0);
1508         }
1509 
1510         float alpha = 1.0;
1511         if (f < 50) alpha = f/50.0;
1512         if (temp_message_frame_to - 50 > frame)
1513             alpha = (temp_message_frame_to-frame)/50.0;
1514 
1515         glColor4f(1.0, 1.0, 0.0, alpha);
1516 
1517         immutable (char)* second_line = msg.find("\n").ptr;
1518         if (second_line == null) second_line = msg.ptr + msg.length;
1519 
1520         glTranslatef(-0.5*msg[0..second_line - msg.ptr].walkLength(), -6.0, 0.0);
1521 
1522         print_text(msg);
1523         
1524         glPopMatrix();
1525     }
1526 
1527     bool paused;
1528     int slow = -1;
1529     int num_stars = 0;
1530     float energy = 100.0;
1531     bool indicators_down;
1532     int inv_num = -1;
1533     STATE state = STATE.NO_DIALOGS;    
1534     
1535     override bool tick(GlobalState gs)    
1536     {
1537         SC sc = SC(cast(int)round(scrx/30), cast(int)round(scry/17));
1538         if (sc in screen_names && sc !in screen_lists && sc !in screens)
1539             return true;
1540         
1541         if (slow >= 0)
1542         {
1543             slow++;
1544             if (slow >= 10) slow = 0;
1545             else return true;
1546         }
1547         
1548         dialogs.tick(gs);
1549 
1550         if (the_hero.energy-0.5 > energy)
1551         {
1552             if (music_state != MUSIC_STATE.ENERGY_PLUS)
1553             {
1554                 music_state = MUSIC_STATE.ENERGY_PLUS;
1555 
1556                 if (the_hero.sounds && energy_plus)
1557                 {   
1558                     if (Mix_PlayMusic(energy_plus, 1) == -1)
1559                     {
1560                         writefln("Mix_PlayMusic: %s",
1561                             Mix_GetError().to!(string)());
1562                     }
1563 
1564                     energy_start_tick = SDL_GetTicks() - cast(long)(1000*energy/100.0);
1565     
1566                     if(Mix_SetMusicPosition(energy/100.0) == -1) {
1567                         writefln("Mix_SetMusicPosition: %s\n",
1568                             Mix_GetError().to!(string)());
1569                     }
1570                 }
1571             }
1572             
1573             energy += 1.0;
1574         }
1575         else if (the_hero.energy+0.5 < energy)
1576         {
1577             if (music_state != MUSIC_STATE.ENERGY_MINUS)
1578             {
1579                 music_state = MUSIC_STATE.ENERGY_MINUS;
1580 
1581                 if (the_hero.sounds && energy_minus)
1582                 {
1583                     if (Mix_PlayMusic(energy_minus, 1) == -1)
1584                     {
1585                         writefln("Mix_PlayMusic: %s",
1586                             Mix_GetError().to!(string)());
1587                     }
1588 
1589                     energy_start_tick = SDL_GetTicks() - cast(long)(1000*(100.0-energy)/100.0);
1590 
1591                     if(Mix_SetMusicPosition((100.0-energy)/100.0) == -1) {
1592                         writefln("Mix_SetMusicPosition: %s\n",
1593                             Mix_GetError().to!(string)());
1594                     }
1595                 }
1596             }
1597             
1598             energy -= 1.0;
1599         }
1600         else
1601         {
1602             if (music_state != MUSIC_STATE.MUSIC &&
1603                 (energy != 100.0 && energy != 0.0 ||
1604                     (SDL_GetTicks() - energy_start_tick) > 2000))
1605             {
1606                 music_state = MUSIC_STATE.MUSIC;
1607 
1608                 if (the_hero.sounds)
1609                 {
1610                     if (music)
1611                     {
1612                         if (Mix_PlayMusic(musics[track], -1) == -1)
1613                         {
1614                             writefln("Mix_PlayMusic: %s",
1615                                 Mix_GetError().to!(string)());
1616                         }
1617                 
1618                         if(Mix_SetMusicPosition((
1619                             (SDL_GetTicks() - music_start_tick)/1000.0)%
1620                             music_len[track]) == -1) {
1621                             writefln("Mix_SetMusicPosition: %s\n",
1622                                 Mix_GetError().to!(string)());
1623                         }
1624                     }
1625                     else
1626                     {
1627                         Mix_HaltMusic();
1628                     }
1629                 }
1630             }
1631         }
1632 
1633         auto b = &branch_quest_variables;
1634 
1635         if (dizzy_throw_branch_quest_state == 1)
1636         {
1637             if (!b.st)
1638             {
1639                 b.st = 1;
1640                 b.x = the_hero.x;
1641                 b.y = the_hero.y;
1642                 b.dx = (366.7 - b.x)/136;
1643                 b.dy = 0.23;
1644                 b.degree = 0.0;
1645             }
1646 
1647             if (b.y < -1.5 && b.dy < 0.0)
1648             {
1649                 dizzy_throw_branch_quest_state++;
1650             }
1651 
1652             b.x += b.dx;
1653             b.y += b.dy;
1654             b.degree += 2.0;
1655 
1656             if (b.dy > -0.1)
1657                 b.dy -= the_hero.MARS_G;
1658         }
1659         else if (dizzy_throw_branch_quest_state == 2)
1660         {
1661             if (dog.state == dog.STATE.GO_LEFT)
1662             {
1663                 dizzy_throw_branch_quest_state++;
1664                 b.st = 0;
1665                 b.x = 0.0;
1666                 b.y = 0.0;
1667                 b.dy = 0.0;
1668             }
1669             
1670             if (b.dy > -0.1)
1671                 b.dy -= the_hero.MARS_G;
1672         }
1673         else if (dizzy_throw_branch_quest_state == 3 &&
1674             (dog.state == dog.STATE.WATCH || dog.state == dog.STATE.FLY_AWAY))
1675         {
1676             dizzy_throw_branch_quest_state++;
1677         }
1678         else if (dizzy_throw_branch_quest_state == 4)
1679         {
1680             b.y += b.dy;
1681             if (b.dy > -0.1)
1682                 b.dy -= the_hero.MARS_G;
1683 
1684             if (b.y < -2.0)
1685             {
1686                 if (dizzy_cuts_rope_quest_state < 0)
1687                     dizzy_throw_branch_quest_state = -1;
1688                 else
1689                     dizzy_throw_branch_quest_state++;
1690 
1691                 branch.x = 358.8;
1692                 branch.y = -5.0;
1693                 branch.used = false;
1694             }
1695         }
1696 
1697         if (state == STATE.DIZZY_USED_KNIFE_ANIM)
1698         {
1699             if (dizzy_used_knife_quest_state == 0 && !the_hero.tick(gs))
1700             {
1701                 dizzy_used_knife_quest_state++;
1702                 collision_objects["solid"].remove("BranchForBreak");
1703                 reset_collision_cache();
1704                 the_hero.reset_anim();
1705                 the_hero.start_fall();
1706             }
1707             else if (dizzy_used_knife_quest_state == 1)
1708             {
1709                 the_hero.tick(gs);
1710                 if (the_hero.frame >= 400)
1711                 {
1712                     dizzy_used_knife_quest_state++;
1713                     state = STATE.NO_DIALOGS;
1714                     the_hero.reset_anim();
1715                 }
1716             }
1717         }
1718         else if (state == STATE.DIZZY_THROW_BRANCH_ANIM)
1719         {
1720             dog.tick(gs);
1721             if (dizzy_throw_branch_quest_state <= 1 && !the_hero.tick(gs))
1722             {
1723                 the_hero.reset_anim();
1724                 state = STATE.NO_DIALOGS;
1725             }
1726             if (the_hero.frame == 45)
1727                     dizzy_throw_branch_quest_state = 1;
1728         }
1729         if (state == STATE.DIZZY_CUTS_ROPE_ANIM)
1730         {
1731             dog.tick(gs);
1732             if (!the_hero.tick(gs))
1733             {
1734                 dog.cut_rope();
1735                 the_hero.reset_anim();
1736                 state = STATE.NO_DIALOGS;
1737             }
1738         }
1739         if (state == STATE.DIZZY_DIG_ANIM)
1740         {
1741             frame++;
1742             ground_garden.tick(gs);
1743             
1744             if (frame - ground_garden.frame == 100)
1745             {
1746                 stone2.x = the_hero.x - 1.0;
1747                 stone2.y = the_hero.y;
1748             }
1749             
1750             if (!the_hero.tick(gs))
1751             {
1752                 the_hero.x = 326.5;
1753                 the_hero.reset_anim();
1754                 state = STATE.NO_DIALOGS;
1755             }
1756         }
1757         if (state == STATE.THINGS_SWEEP_AWAY_ZAKS_ANIM)
1758         {
1759             if (!paused)
1760             {
1761                 frame++;
1762                 things_sweep_away_zaks.tick(gs);
1763                 water3.tick(gs);
1764 
1765                 if (things_sweep_away_zaks.frame > 600)
1766                 {
1767                     stones.frame = frame;
1768                     stones.tick(gs);
1769                     stone3.x = 413.4;
1770                     stone3.y = -84.3;
1771                     state++;
1772                 }
1773             }
1774         }
1775         else if (state != STATE.NO_DIALOGS)
1776         {
1777             if (the_hero.energy <= 0.0)
1778                 the_hero.tick(gs);
1779         }
1780         else if (!paused)
1781         {
1782             //degrees += 1.0;
1783             frame++;
1784             if (things_sweep_away_zaks.frame > 1700) things_sweep_away_zaks.hide();
1785 
1786             the_hero.tick(gs);
1787 
1788             if (the_hero.energy <= 0.0)
1789             {
1790                 if (the_hero.killed_by.startsWith("Stalactite"))
1791                 {
1792                     state = STATE.PIERCED_BY_STALACTITE;
1793                 }
1794                 else if (the_hero.killed_by.startsWith("Stalagmite"))
1795                 {
1796                     state = STATE.PIERCED_BY_STALAGMITE;
1797                 }
1798                 else if (the_hero.killed_by == "Meteorite")
1799                 {
1800                     state = STATE.HIT_BY_METEORITE;
1801                 }
1802                 else if (the_hero.killed_by.startsWith("Acid"))
1803                 {
1804                     state = STATE.DISSOLVED_IN_ACID;
1805                 }
1806                 else if (the_hero.killed_by.startsWith("Lava"))
1807                 {
1808                     state = STATE.BURNED_IN_LAVA;
1809                 }
1810                 else if (the_hero.killed_by.startsWith("Pin"))
1811                 {
1812                     state = STATE.DAMAGED_BY_PIN;
1813                 }
1814                 else if (the_hero.killed_by.startsWith("Rock"))
1815                 {
1816                     state = STATE.HIT_BY_ROCK;
1817                 }
1818                 else if (the_hero.killed_by.startsWith("Flame"))
1819                 {
1820                     state = STATE.BURNED_IN_FLAME;
1821                 }
1822                 else if (the_hero.killed_by.startsWith("Pressure"))
1823                 {
1824                     state = STATE.CRUSHED_BY_PRESSURE;
1825                 }
1826                 else
1827                 {
1828                     assert(0, format("Unknown danger object: %s", the_hero.killed_by));
1829                 }
1830             }
1831 
1832             if (the_hero.x > martian_engineer.x - 1.5 &&
1833                 the_hero.y > martian_engineer.y - 0.5 &&
1834                 martian_engineer.z == 0.0)
1835             {
1836                 state = STATE.MARTIAN_ENGINEER_GET_AWAY;
1837             }
1838 
1839             if (zaks.y == zaks.def_y &&
1840                 the_hero.x > zaks.x - 2.0 &&
1841                 the_hero.y > zaks.y - 0.5 &&
1842                 the_hero.y < zaks.y + 10.5)
1843             {
1844                 the_hero.x = zaks.x - 2.0;
1845             }
1846 
1847             // Location: Water near Zaks
1848             if ( 478.5 < the_hero.x && the_hero.x < 483.6 &&
1849                  the_hero.y < -162.0 )
1850             {
1851                 the_hero.y = -162.0;
1852             }
1853 
1854             // Location: In the bam
1855             if ( 293.7 < the_hero.x && the_hero.x < 304.1 &&
1856                  26.3 < the_hero.y && the_hero.y < 29.2 )
1857             {
1858                 the_hero.z = (the_hero.y-26.3);
1859             }
1860             else if ( the_hero.x >= 280.0 && the_hero.x < 320.0 && 26.2 < the_hero.y && the_hero.y < 29.2 )
1861             {
1862                 the_hero.z = 0.0;
1863             }
1864 
1865             // Location: Two passes and umbrella
1866             if ( the_hero.z < 0.0 && abs(the_hero.x - 511.5) < 4.0  &&
1867                     abs(the_hero.y+4.6) < 2.2 )
1868             {
1869                 the_hero.z = -2.6;
1870             }
1871             else if (the_hero.z < 0.0 && abs(the_hero.x - 511.5) >= 4.0 &&
1872                 abs(the_hero.x-511.5) < 7.0 &&
1873                 abs(the_hero.y+4.6) < 2.2)
1874             {
1875                 the_hero.z = -2.6 + 2.6*(abs(the_hero.x-511.5)-4.0)/3.0;
1876             }
1877             else if (the_hero.z < 0.0 && abs(the_hero.x - 511.5) >= 7.0 &&
1878                 abs(the_hero.x-511.5) < 8.0 &&
1879                 abs(the_hero.y+4.6) < 2.2)
1880             {
1881                 the_hero.z = 0.0;
1882             }
1883 
1884             if (abs(the_hero.x-511.5) < 2.6 &&
1885                 -0.6 < the_hero.y && the_hero.y < 4.3)
1886             {
1887                 the_hero.z = -2.6*(4.3 - the_hero.y)/4.9;
1888             }
1889             else if (abs(the_hero.x-511.5) < 3.6 &&
1890                 -0.6 < the_hero.y && the_hero.y < 5.3)
1891             {
1892                 the_hero.z = 0.0;
1893             }
1894 
1895             foreach (animation; animations)
1896             {
1897                 animation.tick(gs);
1898             }
1899 
1900             bag_bug_anim.tick(gs);
1901 
1902             switch(rope_state)
1903             {
1904                 case 0:
1905                     the_hero.rope = null;
1906                     break;
1907                 case 1:
1908                     the_hero.rope = rope1;
1909                     rope1.tick(gs);
1910                     break;
1911                 case 2:
1912                     the_hero.rope = rope2;
1913                     rope2.tick(gs);
1914                     break;
1915                 case 3:
1916                     the_hero.rope = rope3;
1917                     rope3.tick(gs);
1918                     break;
1919                 default:
1920                     assert(0);
1921             }
1922 
1923             if ((bucket_of_water.inventory ||
1924                  bucket_covered.inventory) &&
1925                  the_hero.fall && bucket_anim.frame < 0)
1926             {
1927                 foreach(i, ref item_num; inventory)
1928                 {
1929                     if (items[item_num] == bucket_of_water)
1930                     {
1931                         bucket_of_water.inventory = false;
1932                         bucket_of_water.used = true;
1933                         inventory = inventory[0..i]~inventory[i+1..$];
1934                         break;
1935                     }
1936                 }
1937                 foreach(i, ref item_num; inventory)
1938                 {
1939                     if (items[item_num] == bucket_covered)
1940                     {
1941                         bucket_covered.inventory = false;
1942                         bucket_covered.used = true;
1943                         item_num += 3;
1944                         break;
1945                     }
1946                 }
1947                 bucket_anim.start_anim([the_hero.x, the_hero.y, the_hero.z]);
1948             }
1949 
1950             if (bucket_anim.frame >= 0 &&
1951                 frame - bucket_anim.frame >= 200)
1952             {
1953                 bucket_anim.frame = -1;
1954                 bucket.used = false;
1955                 bucket.inventory = false;
1956                 bucket.x = the_hero.x - 2.0;
1957                 bucket.y = the_hero.y;
1958                 bucket.z = the_hero.z;
1959             }
1960 
1961             if (abs(scrx - 330.0f) < 1.0f && abs(scry + 17.0f) < 1.0f && track == 0)
1962             {
1963                 track = 1;
1964                 music_start_tick = cast(long)SDL_GetTicks();
1965                 play_music();
1966             }
1967 
1968             // Location: Dangerous deep
1969             if (abs(scrx - 240.0f) < 1.0f && abs(scry + 85.0f) < 1.0f)
1970             {
1971                 if (!pressprot.inventory)
1972                 {
1973                     the_hero.energy = min(the_hero.energy, (the_hero.y + 93.0f)/16.0f*100.0f);
1974                     if (the_hero.energy <= 0.0)
1975                     {
1976                         the_hero.die("Pressure");
1977                     }
1978                 }
1979             }
1980 
1981             // Location: And can not see the bottom
1982             if (abs(scrx - 240.0f) < 1.0f && abs(scry + 136.0f) < 1.0f)
1983             {
1984                 the_hero.energy = min(the_hero.energy, (the_hero.y + 144.0f)/10.0f*100.0f);
1985                 if (the_hero.energy <= 0.0)
1986                 {
1987                     the_hero.die("Pressure");
1988                 }
1989             }
1990 
1991             // Location: The mine
1992             if (abs(scrx - 330.0f) < 1.0f && abs(scry + 34.0f) < 1.0f &&
1993                 grasshopper_item.inventory && bird.fly == 0)
1994             {
1995                 bird.start_fly();
1996                 track = 2;
1997                 music_start_tick = cast(long)SDL_GetTicks();
1998                 play_music();
1999             }
2000 
2001             float oldscrx = scrx, oldscry = scry;
2002 
2003             while (the_hero.x-scrx > 15.0)
2004             {
2005                 scrx += 30.0;
2006             }
2007             
2008             while (the_hero.x-scrx < -15.0)
2009             {
2010                 scrx -= 30.0;
2011             }
2012 
2013             while (the_hero.y-scry > 8.5)
2014             {
2015                 scry += 17.0;
2016             }
2017 
2018             while (the_hero.y-scry < -8.5)
2019             {
2020                 scry -= 17.0;
2021             }
2022 
2023             if ( abs(scrx - 510.0) < 1.0 && abs(scry + 153.0) < 1.0 )
2024             {
2025                 the_hero.force_dx = -0.15;
2026                 the_hero.dy = the_hero.JUMP_V;
2027                 if (the_hero.lives < 0) the_hero.lives = 0;
2028                 state = state.TO_BE_CONTINUED_MESSAGE;
2029                 scrx -= 30.0;
2030             }
2031 
2032             sc = SC(cast(int)round(scrx/30), cast(int)round(scry/17));
2033             if (sc !in screen_names)
2034             {
2035                 scrx = oldscrx;
2036                 scry = oldscry;
2037             }
2038 
2039             if ( (oldscrx != scrx || oldscry != scry) &&
2040                   abs(scrx - 15*30.0) < 1.0 && abs(scry + 7*17.0) < 1.0 &&
2041                   track == 4 &&
2042                   all_items_in_the_castle() && rope.in_the_castle() )
2043             {
2044                 track = 3;
2045                 music_start_tick = cast(long)SDL_GetTicks();
2046                 play_music();
2047             }
2048 
2049             if (oldscrx != scrx || oldscry!=scry)
2050             {
2051                 sl_tid.send(cast(int) round(scrx/30.0),
2052                     cast(int) round(scry/17.0));
2053             }
2054 
2055             if (explosure.frame >= 0 && abs(scrx - 420.0) < 1.0 &&
2056                 abs(scry - 0.0) < 1.0)
2057             {
2058                 dizzy_live_after_explosure_quest_state = 1;
2059             }
2060 
2061             if (wait_meteorite < 0 && "Martian_Agronomist_Gives_Bucket" in done_dialogs &&
2062                 oldscrx < 149 && scrx > 149)
2063             {
2064                 wait_meteorite = 0;
2065             }
2066 
2067             if (wait_meteorite2 < 0 && bird.x < 170.0)
2068             {
2069                 wait_meteorite2 = 0;
2070             }
2071 
2072             if (bucket_of_water.inventory && abs(scrx - 360.0) < 1.0 &&
2073                 abs(scry - 0.0) < 1.0)
2074             {
2075                 foreach(i, ref item_num; inventory)
2076                 {
2077                     if (items[item_num] == bucket_of_water)
2078                     {
2079                         bucket_of_water.inventory = false;
2080                         bucket_of_water.used = true;
2081                         bucket_of_ice.inventory = true;
2082                         bucket_of_ice.used = false;
2083                         item_num++;
2084                         break;
2085                     }
2086                 }
2087             }
2088         }
2089         
2090         return true;
2091     }
2092 
2093     void print_message(TEMP_MESSAGES msg, string str = null)
2094     {
2095         temp_message = msg;
2096         temp_message_str = str;
2097         temp_message_frame_from = frame;
2098         temp_message_frame_to = frame+200;
2099     }
2100 
2101     void pause(GlobalState gs)
2102     {
2103         paused = !paused;
2104     }
2105 
2106     void
2107     process_event(GlobalState gs, SDL_Event event)
2108     {
2109         
2110     }
2111 
2112     void
2113     quit(GlobalState gs)
2114     {
2115         gs.stopGame();
2116     }
2117 
2118     void
2119     start_left(GlobalState gs)
2120     {
2121         if (!(keys & LEFT_KEY))
2122         {
2123             keys |= LEFT_KEY;
2124             the_hero.start_left(gs);
2125         }
2126     }
2127 
2128     void stop_left(GlobalState gs)
2129     {
2130         if (keys & LEFT_KEY)
2131         {
2132             keys &= ~LEFT_KEY;
2133             the_hero.stop_left(gs);
2134         }
2135     }
2136 
2137     void
2138     start_right(GlobalState gs)
2139     {
2140         if (!(keys & RIGHT_KEY))
2141         {
2142             keys |= RIGHT_KEY;
2143             the_hero.start_right(gs);
2144         }
2145     }
2146 
2147     void stop_right(GlobalState gs)
2148     {
2149         if (keys & RIGHT_KEY)
2150         {
2151             keys &= ~RIGHT_KEY;
2152             the_hero.stop_right(gs);
2153         }
2154     }
2155 
2156     void start_jump(GlobalState gs)
2157     {
2158         if (state == STATE.INVENTORY)
2159         {
2160             inv_num--;
2161             if (inv_num < -1) inv_num = cast(int)(inventory.length-1);
2162         }
2163         else if (!(keys & UP_KEY))
2164         {
2165             the_hero.start_jump(gs);
2166         }
2167         
2168         keys |= UP_KEY;
2169     }
2170 
2171     void stop_jump(GlobalState gs)
2172     {
2173         keys &= ~UP_KEY;
2174     }
2175 
2176     void down(GlobalState gs)
2177     {
2178         if (state == STATE.INVENTORY)
2179         {
2180             inv_num++;
2181             if (inv_num >= inventory.length) inv_num = -1;
2182         }
2183         keys |= DOWN_KEY;
2184     }
2185 
2186     void stop_down(GlobalState gs)
2187     {
2188         keys &= ~DOWN_KEY;
2189     }
2190 
2191     void change_language(GlobalState gs)
2192     {
2193         lang++;
2194         if (lang > LANG.MAX) lang = LANG.EN;
2195     }
2196 
2197     void print_coords(GlobalState gs)
2198     {
2199         writefln("x=%s, y=%s, z=%s", the_hero.x, the_hero.y, the_hero.z);
2200     }
2201 
2202     void switch_slow(GlobalState gs)
2203     {
2204         if (keys & CTRL_KEY) return save(gs);
2205         if (slow >= 0) slow = -1;
2206         else slow = 0;
2207     }
2208 
2209     void switch_sensors(GlobalState gs)
2210     {
2211         the_hero.show_sensors = !the_hero.show_sensors;
2212     }
2213 
2214     void ctrl_down(GlobalState gs)
2215     {
2216         keys |= CTRL_KEY;
2217     }
2218 
2219     void ctrl_up(GlobalState gs)
2220     {
2221         keys &= ~CTRL_KEY;
2222     }
2223 
2224     void shift_down(GlobalState gs)
2225     {
2226         keys |= SHIFT_KEY;
2227     }
2228 
2229     void shift_up(GlobalState gs)
2230     {
2231         keys &= ~SHIFT_KEY;
2232     }
2233 
2234     void action(GlobalState gs)
2235     {
2236         switch_label:
2237         final switch(state)
2238         {
2239             case STATE.NO_DIALOGS:
2240 
2241                 foreach(i, star; stars)
2242                 {
2243                     if (star.maybe_taken(gs, the_hero))
2244                     {
2245                         state = STATE.ENERGY_STAR;
2246                         num_stars++;
2247                         the_hero.energy += 25.0;
2248                         if (the_hero.energy > 100.0)
2249                         {
2250                             the_hero.energy = 100.0;
2251                             if (energy == 100.0) energy = 99.0;
2252                         }
2253                         star.take();
2254                         break switch_label;
2255                     }
2256                 }
2257 
2258                 if (bag.maybe_taken(gs, the_hero))
2259                 {
2260                     max_items = 5;
2261                     bag.used = true;
2262                     state = STATE.BAG_FOUND;
2263                     break switch_label;
2264                 }
2265 
2266                 bool stone_place = abs(the_hero.x-242.6) < 3.0 &&
2267                         abs(the_hero.y+5.0) < 0.5;
2268                 bool stone_in_inventory = stone_place && (stone1.inventory || stone2.inventory);
2269                 bool bug_place = abs(the_hero.x-242.6) < 3.0 &&
2270                         abs(the_hero.y+5.0) < 0.5;
2271 
2272                 foreach(i, ref item; items)
2273                 {
2274                     if (item.maybe_taken(gs, the_hero) && 
2275                         (item.model != "stone1" && 
2276                             item.model != "stone2" || !stone_in_inventory))
2277                     {
2278                         if (inventory.length >= max_items)
2279                         {
2280                             state = STATE.TOO_MANY_ITEMS;
2281                             break switch_label;
2282                         }
2283                         
2284                         inventory ~= i;
2285                         item.inventory = true;
2286 
2287                         state = STATE.INVENTORY;
2288                         inv_num = -1;
2289                         break switch_label;
2290                     }
2291                 }
2292 
2293                 // Location: Martian-Agronomist
2294                 if (abs(the_hero.x-282.25) < 2.6 && abs(the_hero.y-0.95) < 0.5 && !the_hero.jump)
2295                 {
2296                     if ("Martian_Agronomist_Hello" !in done_dialogs)
2297                     {
2298                         done_dialogs["Martian_Agronomist_Hello"] = true;
2299                         state = STATE.MARTIAN_AGRONOMIST_HELLO;
2300                         break switch_label;
2301                     }
2302 
2303                     if (dizzy_throw_branch_quest_state >= 5 &&
2304                         "Martian_Agronomist_Rope" !in done_dialogs)
2305                     {
2306                         done_dialogs["Martian_Agronomist_Rope"] = true;
2307                         state = STATE.MARTIAN_AGRONOMIST_ROPE;
2308                         break switch_label;
2309                     }
2310 
2311                     if ("Martian_Chemist_Hello" in done_dialogs &&
2312                         "Martian_Agronomist_Gives_Bucket" !in done_dialogs)
2313                     {
2314                         done_dialogs["Martian_Agronomist_Gives_Bucket"] = true;
2315                         state = STATE.MARTIAN_AGRONOMIST_GIVES_BUCKET;
2316                         break switch_label;
2317                     }
2318 
2319                     if (dizzy_water_flowers_state == 1 &&
2320                         "Martian_Agronomist_Thanks" !in done_dialogs)
2321                     {
2322                         done_dialogs["Martian_Agronomist_Thanks"] = true;
2323                         state = STATE.MARTIAN_AGRONOMIST_THANKS;
2324                         break switch_label;
2325                     }
2326                 }
2327 
2328                 // Location: Martian-Engineer
2329                 if (abs(the_hero.x-402.0) < 2.6 && abs(the_hero.y-2.7) < 0.5 && !the_hero.jump)
2330                 {
2331                     if ("Martian_Agronomist_Thanks" in done_dialogs &&
2332                         "Martian_Engineer_Returns_Player" !in done_dialogs)
2333                     {
2334                         done_dialogs["Martian_Engineer_Returns_Player"] = true;
2335                         state = STATE.MARTIAN_ENGINEER_RETURNS_PLAYER;
2336                         break switch_label;
2337                     }
2338 
2339                     if ((light_branch.inventory ||
2340                         light_branch.def_x != light_branch.x ||
2341                         light_branch.def_y != light_branch.y) &&
2342                         "Martian_Engineer_Gives_Spade" !in done_dialogs)
2343                     {
2344                         done_dialogs["Martian_Engineer_Gives_Spade"] = true;
2345                         state = STATE.MARTIAN_ENGINEER_GIVES_SPADE;
2346                         break switch_label;
2347                     }
2348 
2349                     if (squid_item.used && bird_item.used &&
2350                         "Martian_Engineer_Returns_Bucket" !in done_dialogs)
2351                     {
2352                         done_dialogs["Martian_Engineer_Returns_Bucket"] = true;
2353                         state = STATE.MARTIAN_ENGINEER_RETURNS_BUCKET;
2354                         break switch_label;
2355                     }
2356 
2357                     if (bug.sprayed && grasshopper.sprayed &&
2358                         whistle.def_x == whistle.x &&
2359                         whistle.def_y == whistle.y)
2360                     {
2361                         state = STATE.MARTIAN_ENGINEER_GIVES_WHISTLE;
2362                         break switch_label;
2363                     }
2364                 }
2365 
2366                 // Location: Door in the cave of light tree (Outdoor)
2367                 if (key.used && abs(the_hero.x-16.5) < 1.5 && abs(the_hero.y-0.7) < 0.5 && !the_hero.jump)
2368                 {
2369                     the_hero.y = 26.8;
2370                     break switch_label;
2371                 }
2372 
2373                 // Location: Door in the cave of light tree (Indoor)
2374                 if (abs(the_hero.x-16.5) < 1.5 && abs(the_hero.y-26.8) < 0.5 && !the_hero.jump)
2375                 {
2376                     the_hero.y = 0.7;
2377                     break switch_label;
2378                 }
2379 
2380                 // Location: Door in the undercave (Outdoor)
2381                 if (abs(the_hero.x-36.2) < 1.5 && abs(the_hero.y-34.9) < 0.5 && !the_hero.jump)
2382                 {
2383                     the_hero.y = 68.9;
2384                     break switch_label;
2385                 }
2386 
2387                 // Location: Door in the undercave (Indoor)
2388                 if (abs(the_hero.x-36.2) < 1.5 && abs(the_hero.y-68.9) < 0.5 && !the_hero.jump)
2389                 {
2390                     the_hero.y = 34.9;
2391                     break switch_label;
2392                 }
2393 
2394                 // Location: Door of bam (Outdoor)
2395                 if (abs(the_hero.x-311.5) < 1.5 && abs(the_hero.y+0.1) < 0.5 && !the_hero.jump)
2396                 {
2397                     the_hero.x = 304.7;
2398                     the_hero.y = 26.2;
2399                     bag_bug_anim.start();
2400                     break switch_label;
2401                 }
2402 
2403                 // Location: Door of bam (Indoor)
2404                 if (abs(the_hero.x-304.7) < 1.5 && abs(the_hero.y-26.2) < 0.5 && !the_hero.jump)
2405                 {
2406                     the_hero.x = 311.5;
2407                     the_hero.y = -0.1;
2408                     break switch_label;
2409                 }
2410 
2411                 // Location: Booth (Outdoor)
2412                 if (abs(the_hero.x-308.7) < 1.5 && abs(the_hero.y+6.2) < 0.5 && !the_hero.jump)
2413                 {
2414                     state = STATE.LOOKING_BOOTH_MESSAGE;
2415                     break switch_label;
2416                 }
2417 
2418                 // Location : near branch under tree
2419                 if (dizzy_used_knife_quest_state == 2 && 
2420                     abs(the_hero.x-327.0) < 1.5 && abs(the_hero.y+6.0) < 0.5 && !the_hero.jump)
2421                 {                                                        
2422                     if (inventory.length >= max_items)
2423                     {
2424                         state = STATE.TOO_MANY_ITEMS;
2425                         break switch_label;
2426                     }
2427                     
2428                     foreach(i, ref item; items)
2429                     {
2430                         if (item.model == "branch")
2431                         {
2432                             dizzy_used_knife_quest_state++;
2433                             
2434                             inventory ~= i;
2435                             item.inventory = true;
2436                             break;
2437                         }
2438                     }
2439                 }
2440 
2441                 // Location : Danger sign in the muzzle of volcano
2442                 if (rope_state == 1 &&
2443                     abs(the_hero.x-418.1) < 1.5 &&
2444                     abs(the_hero.y-1.0) < 0.5 && !the_hero.jump)
2445                 {
2446                     foreach(i, ref item; items)
2447                     {
2448                         if (item.model == "rope")
2449                         {
2450                             if (inventory.length >= max_items)
2451                             {
2452                                 state = STATE.TOO_MANY_ITEMS;
2453                                 break switch_label;
2454                             }
2455                             
2456                             state = STATE.DIZZY_UNTIED_ROPE_MESSAGE;
2457                             inventory ~= i;
2458                             item.inventory = true;
2459                             item.used = false;
2460                     
2461                             break switch_label;
2462                         }
2463                     }
2464                 }
2465 
2466                 // Location : Danger sign before Martian-Agronomist
2467                 if (rope_state == 2 &&
2468                     abs(the_hero.x-245.0) < 1.5 &&
2469                     abs(the_hero.y-2.0) < 0.5 && !the_hero.jump)
2470                 {
2471                     foreach(i, ref item; items)
2472                     {
2473                         if (item.model == "rope")
2474                         {
2475                             if (inventory.length >= max_items)
2476                             {
2477                                 state = STATE.TOO_MANY_ITEMS;
2478                                 break switch_label;
2479                             }
2480                             
2481                             state = STATE.DIZZY_UNTIED_ROPE_MESSAGE;
2482                             inventory ~= i;
2483                             item.inventory = true;
2484                             item.used = false;
2485                     
2486                             break switch_label;
2487                         }
2488                     }
2489                 }
2490 
2491                 // Location : Danger sign underground
2492                 if (rope_state == 3 &&
2493                     abs(the_hero.x-331.2) < 1.5 &&
2494                     abs(the_hero.y+14.0) < 0.5 && !the_hero.jump)
2495                 {
2496                     foreach(i, ref item; items)
2497                     {
2498                         if (item.model == "rope")
2499                         {
2500                             if (inventory.length >= max_items)
2501                             {
2502                                 state = STATE.TOO_MANY_ITEMS;
2503                                 break switch_label;
2504                             }
2505                             
2506                             state = STATE.DIZZY_UNTIED_ROPE_MESSAGE;
2507                             inventory ~= i;
2508                             item.inventory = true;
2509                             item.used = false;
2510                     
2511                             break switch_label;
2512                         }
2513                     }
2514                 }
2515 
2516                 // Location : Near tree with the dog, rope
2517                 if (dizzy_cuts_rope_quest_state >= 0 &&
2518                     dizzy_throw_branch_quest_state >= 5 &&
2519                     dog.hidden == 1 &&
2520                     short_rope.x == short_rope.def_x &&
2521                     short_rope.y == short_rope.def_y &&
2522                     abs(the_hero.x-359.2) < 1.5 && abs(the_hero.y+5.0) < 0.5 && !the_hero.jump)
2523                 {
2524                     foreach(i, ref item; items)
2525                     {
2526                         if (item.model == "short-rope")
2527                         {
2528                             if (inventory.length >= max_items)
2529                             {
2530                                 state = STATE.TOO_MANY_ITEMS;
2531                                 break switch_label;
2532                             }
2533                             
2534                             state = STATE.DIZZY_UNTIED_SHORT_ROPE_MESSAGE;
2535                             inventory ~= i;
2536                             item.inventory = true;
2537                             item.used = false;
2538                             dog.hide();
2539                     
2540                             break switch_label;
2541                         }
2542                     }
2543                 }
2544 
2545                 // Location: Martian-Chemist
2546                 if (abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2547                 {
2548                     if ("Martian_Chemist_Hello" !in done_dialogs)
2549                     {
2550                         done_dialogs["Martian_Chemist_Hello"] = true;
2551                         state = STATE.MARTIAN_CHEMIST_HELLO;
2552                         break switch_label;
2553                     }
2554                 }
2555 
2556                 // Location : Cave with grasshopper
2557                 if (ground_cave.frame >= 0 &&
2558                     !grasshopper.killed &&
2559                     grasshopper.y < 62.4 &&
2560                     abs(grasshopper.x-30.3) < 2.0 &&
2561                     abs(the_hero.x-30.3) < 3.0 &&
2562                     abs(the_hero.y-62.7) < 0.5 && !the_hero.jump)
2563                 {
2564                     foreach(i, ref item; items)
2565                     {
2566                         if (item.model == "grasshopper-0")
2567                         {
2568                             if (inventory.length >= max_items)
2569                             {
2570                                 state = STATE.TOO_MANY_ITEMS;
2571                                 break switch_label;
2572                             }
2573                             
2574                             state = STATE.DIZZY_CATCH_GRASSHOPPER_MESSAGE;
2575                             inventory ~= i;
2576                             item.inventory = true;
2577                             item.used = false;                                    
2578                             grasshopper.kill();
2579                             break switch_label;
2580                         }
2581                     }
2582                 }
2583 
2584                 state = STATE.INVENTORY;
2585                 inv_num = -1;
2586                 break;
2587             case STATE.INVENTORY:
2588                 if (inv_num >= 0)
2589                 {
2590                     // Location : On Tree
2591                     if (items[inventory[inv_num]].model == "kitchen-knife" && 
2592                         abs(the_hero.x-327.0) < 1.5 && abs(the_hero.y-2.3) < 0.5 && !the_hero.jump)
2593                     {
2594                         state = STATE.DIZZY_USED_KNIFE_MESSAGE;
2595                         dizzy_used_knife_quest_state = 0;
2596                         the_hero.use_knife();
2597                         break switch_label;
2598                     }
2599 
2600                     // Location : Near tree with the dog
2601                     if (items[inventory[inv_num]].model == "branch" && 
2602                         dizzy_throw_branch_quest_state == -1 &&
2603                         abs(the_hero.x-354.1) < 3 && abs(the_hero.y+5.0) < 0.5 && !the_hero.jump)
2604                     {
2605                         state = STATE.DIZZY_THROW_BRANCH_MESSAGE;
2606                         dizzy_throw_branch_quest_state = 0;
2607                         the_hero.throw_branch();
2608                         
2609                         inventory = inventory[0..inv_num] ~ inventory[inv_num+1..$];
2610                         branch.inventory = false;
2611                         branch.used = true;
2612                         
2613                         break switch_label;
2614                     }
2615 
2616                     // Location : Near tree with the dog, rope
2617                     if (items[inventory[inv_num]].model == "kitchen-knife" &&
2618                         dizzy_cuts_rope_quest_state == -1 &&
2619                         abs(the_hero.x-359.2) < 1.5 && abs(the_hero.y+5.0) < 0.5 && !the_hero.jump)
2620                     {
2621                         state = STATE.DIZZY_CUTS_ROPE_MESSAGE;
2622                         dizzy_cuts_rope_quest_state = 0;
2623                         the_hero.cut_rope();               
2624                         break switch_label;
2625                     }
2626 
2627                     // Location : Martian-Engineer
2628                     if (items[inventory[inv_num]].model == "player" &&
2629                         "Martian_Engineer_Takes_Player" !in done_dialogs &&
2630                         abs(the_hero.x-martian_engineer.x) < 4.0 &&
2631                         abs(the_hero.y-martian_engineer.y) < 0.5 && !the_hero.jump)
2632                     {
2633                         done_dialogs["Martian_Engineer_Takes_Player"] = true;
2634                         state = STATE.MARTIAN_ENGINEER_TAKES_PLAYER;
2635                         inventory = inventory[0..inv_num] ~ inventory[inv_num+1..$];
2636                         player.inventory = false;
2637                         player.used = true;
2638                         
2639                         break switch_label;
2640                     }
2641                     if (items[inventory[inv_num]].model == "bucket-of-ice" &&
2642                         "Martian_Engineer_Returns_Player" in done_dialogs &&
2643                         "Martian_Engineer_Takes_Bucket" !in done_dialogs &&
2644                         abs(the_hero.x-402.0) < 2.6 && abs(the_hero.y-2.7) < 0.5 && !the_hero.jump)
2645                     {
2646                         done_dialogs["Martian_Engineer_Takes_Bucket"] = true;
2647                         state = STATE.MARTIAN_ENGINEER_TAKES_BUCKET;
2648                         //inventory[inv_num] -= 2;
2649                         bucket_of_ice.inventory = false;
2650                         bucket_of_ice.used = true;
2651                         //bucket.inventory = true;
2652                         //bucket.used = false;
2653                         inventory = inventory[0..inv_num] ~ inventory[inv_num+1..$];
2654                         
2655                         break switch_label;
2656                     }
2657 
2658                     if (items[inventory[inv_num]].model == "bucket-of-ice" &&
2659                         "Martian_Engineer_Returns_Player" in done_dialogs &&
2660                         abs(the_hero.x-402.0) < 2.6 && abs(the_hero.y-2.7) < 0.5 && !the_hero.jump)
2661                     {
2662                         done_dialogs["Martian_Engineer_Takes_Bucket"] = true;
2663                         state = STATE.MARTIAN_ENGINEER_TAKES_BUCKET;
2664                         inventory[inv_num] -= 2;
2665                         bucket_of_ice.inventory = false;
2666                         bucket_of_ice.used = true;
2667                         bucket.inventory = true;
2668                         bucket.used = false;
2669                         
2670                         break switch_label;
2671                     }
2672 
2673                     // Location: Martian-Chemist
2674                     if (items[inventory[inv_num]].model == "grasshoppers-poison" &&
2675                         abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2676                     {
2677                         if (!grasshopper_item.inventory ||
2678                             !bird_item.inventory)
2679                         {
2680                             state = STATE.MARTIAN_CHEMIST_NO_GRASSHOPPER;
2681                             break switch_label;
2682                         }
2683                     }
2684                     if (items[inventory[inv_num]].model == "grasshopper-0" &&
2685                         abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2686                     {
2687                         if (!grasshoppers_poison.inventory ||
2688                             !bird_item.inventory)
2689                         {
2690                             state = STATE.MARTIAN_CHEMIST_NO_BIRD;
2691                             break switch_label;
2692                         }
2693                     }
2694                     if (items[inventory[inv_num]].model == "bird-item" &&
2695                         abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2696                     {
2697                         if (!grasshoppers_poison.inventory ||
2698                             !grasshopper_item.inventory)
2699                         {
2700                             state = STATE.MARTIAN_CHEMIST_NO_GRASSHOPPERS_POISON;
2701                             break switch_label;
2702                         }
2703                     }
2704                     if ((items[inventory[inv_num]].model == "grasshoppers-poison" ||
2705                          items[inventory[inv_num]].model == "grasshopper-0" ||
2706                          items[inventory[inv_num]].model == "bird-item") &&
2707                         abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2708                     {
2709                         if (grasshoppers_poison.inventory &&
2710                             grasshopper_item.inventory &&
2711                             bird_item.inventory)
2712                         {
2713                             grasshoppers_poison.used = true;
2714                             grasshopper_item.used = true;
2715                             bird_item.used = true;
2716 
2717                             size_t[] new_inv;
2718                             foreach (inv; inventory)
2719                             {
2720                                 if (items[inv].model != "grasshoppers-poison" &&
2721                                     items[inv].model != "grasshopper-0" &&
2722                                     items[inv].model != "bird-item")
2723                                 {
2724                                     new_inv ~= inv;
2725                                 }
2726                             }
2727                             inventory = new_inv;
2728                             
2729                             if (!bugs_poison.used)
2730                                 state = STATE.MARTIAN_CHEMIST_THANK_YOU;
2731                             else
2732                                 state = STATE.MARTIAN_CHEMIST_NEED_WATER_FROM_LIGHT_TREE_CAVE;
2733                             break switch_label;
2734                         }
2735                     }
2736 
2737                     // Location: Martian-Chemist
2738                     if (items[inventory[inv_num]].model == "bugs-poison" &&
2739                         abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2740                     {
2741                         if (!bug_item.inventory ||
2742                             !fish_item.inventory ||
2743                             !squid_item.inventory)
2744                         {
2745                             state = STATE.MARTIAN_CHEMIST_NO_BUG;
2746                             break switch_label;
2747                         }
2748                     }
2749                     if (items[inventory[inv_num]].model == "bug" &&
2750                         abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2751                     {
2752                         if (!bugs_poison.inventory ||
2753                             !fish_item.inventory ||
2754                             !squid_item.inventory)
2755                         {
2756                             state = STATE.MARTIAN_CHEMIST_NO_FISH;
2757                             break switch_label;
2758                         }
2759                     }
2760                     if (items[inventory[inv_num]].model == "fish-item" &&
2761                         abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2762                     {
2763                         if (!bugs_poison.inventory ||
2764                             !bug_item.inventory ||
2765                             !squid_item.inventory)
2766                         {
2767                             state = STATE.MARTIAN_CHEMIST_NO_SQUID;
2768                             break switch_label;
2769                         }
2770                     }
2771                     if (items[inventory[inv_num]].model == "squid-item" &&
2772                         abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2773                     {
2774                         if (!bugs_poison.inventory ||
2775                             !bug_item.inventory ||
2776                             !fish_item.inventory)
2777                         {
2778                             state = STATE.MARTIAN_CHEMIST_NO_BUGS_POISON;
2779                             break switch_label;
2780                         }
2781                     }
2782                     if ((items[inventory[inv_num]].model == "bugs-poison" ||
2783                          items[inventory[inv_num]].model == "bug" ||
2784                          items[inventory[inv_num]].model == "fish-item" ||
2785                          items[inventory[inv_num]].model == "squid-item") &&
2786                         abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2787                     {
2788                         if (bugs_poison.inventory &&
2789                             bug_item.inventory &&
2790                             fish_item.inventory &&
2791                             squid_item.inventory)
2792                         {
2793                             bugs_poison.used = true;
2794                             bug_item.used = true;
2795                             fish_item.used = true;
2796                             squid_item.used = true;
2797 
2798                             size_t[] new_inv;
2799                             foreach (inv; inventory)
2800                             {
2801                                 if (items[inv].model != "bugs-poison" &&
2802                                     items[inv].model != "bug" &&
2803                                     items[inv].model != "fish-item" &&
2804                                     items[inv].model != "squid-item")
2805                                 {
2806                                     new_inv ~= inv;
2807                                 }
2808                             }
2809                             inventory = new_inv;
2810                             
2811                             if (!grasshoppers_poison.used)
2812                                 state = STATE.MARTIAN_CHEMIST_THANK_YOU;
2813                             else
2814                                 state = STATE.MARTIAN_CHEMIST_NEED_WATER_FROM_LIGHT_TREE_CAVE;
2815                             break switch_label;
2816                         }
2817                     }
2818 
2819                     // Location: Martian-Chemist
2820                     if (items[inventory[inv_num]].model == "bucket-with-light-water" &&
2821                         abs(the_hero.x-463.2) < 2.6 && abs(the_hero.y-1.7) < 0.5 && !the_hero.jump)
2822                     {
2823                         state = STATE.MARTIAN_CHEMIST_GIVES_PSYCHOTROPIC_SPRAY;
2824                         inventory = inventory[0..inv_num] ~ inventory[inv_num+1..$];
2825                         bucket_with_light_water.inventory = false;
2826                         bucket_with_light_water.used = true;
2827                         
2828                         break switch_label;
2829                     }
2830 
2831 
2832                     // Location : Danger sign in the muzzle of volcano
2833                     if (items[inventory[inv_num]].model == "rope" &&
2834                         abs(the_hero.x-418.1) < 1.5 &&
2835                         abs(the_hero.y-1.0) < 0.5 && !the_hero.jump)
2836                     {
2837                         state = STATE.DIZZY_TIED_ROPE_MESSAGE;
2838                         inventory = inventory[0..inv_num] ~ inventory[inv_num+1..$];
2839                         rope.inventory = false;
2840                         rope.used = true;
2841                         
2842                         break switch_label;
2843                     }
2844 
2845                     // Location : Danger sign before Martian-Agronomist
2846                     if (items[inventory[inv_num]].model == "rope" &&
2847                         abs(the_hero.x-245.0) < 1.5 &&
2848                         abs(the_hero.y-2.0) < 0.5 && !the_hero.jump)
2849                     {
2850                         state = STATE.DIZZY_TIED_ROPE_MESSAGE;
2851                         inventory = inventory[0..inv_num] ~ inventory[inv_num+1..$];
2852                         rope.inventory = false;
2853                         rope.used = true;
2854                         
2855                         break switch_label;
2856                     }
2857 
2858                     // Location : Danger sign underground
2859                     if (items[inventory[inv_num]].model == "rope" &&
2860                         abs(the_hero.x-331.2) < 1.5 &&
2861                         abs(the_hero.y+14.0) < 0.5 && !the_hero.jump)
2862                     {
2863                         state = STATE.DIZZY_TIED_ROPE_MESSAGE;
2864                         inventory = inventory[0..inv_num] ~ inventory[inv_num+1..$];
2865                         rope.inventory = false;
2866                         rope.used = true;
2867                         
2868                         break switch_label;
2869                     }
2870 
2871                     if (items[inventory[inv_num]].model == "stunning-drink")
2872                     {
2873                         state = STATE.DIZZY_DRINK_STUNNING_MESSAGE;
2874                         break switch_label;
2875                     }
2876 
2877                     // Location : Well
2878                     if ((items[inventory[inv_num]].model == "bucket" ||
2879                          items[inventory[inv_num]].model == "bucket-of-ice") &&
2880                         rope.inventory &&
2881                         abs(the_hero.x-118.8) < 1.5 &&
2882                         abs(the_hero.y+4.1) < 0.5 && !the_hero.jump)
2883                     {
2884                         if (dizzy_water_flowers_state < 0)
2885                         {
2886                             state = STATE.DIZZY_TRIES_FILL_BUCKET_MESSAGE;
2887                         }
2888                         else
2889                         {
2890                             state = STATE.DIZZY_FILL_BUCKET_MESSAGE;
2891                         }
2892                         break switch_label;
2893                     }
2894                     if (items[inventory[inv_num]].model == "meteorite" &&
2895                         abs(the_hero.x-118.8) < 1.5 &&
2896                         abs(the_hero.y+4.1) < 0.5 && !the_hero.jump)
2897                     {
2898                         state = STATE.DIZZY_THROW_METEORITE_MESSAGE;
2899                         inventory = inventory[0..inv_num] ~ inventory[inv_num+1..$];
2900                         meteorite.inventory = false;
2901                         meteorite.used = true;
2902                         dizzy_water_flowers_state = 0;
2903                         break switch_label;
2904                     }
2905 
2906                     // Location : Garden of agronomist
2907                     if (dizzy_water_flowers_state < 1 &&
2908                         items[inventory[inv_num]].model == "bucket-of-water" &&
2909                         abs(the_hero.x-276.0) < 3.0 &&
2910                         abs(the_hero.y+8.1) < 0.5 && !the_hero.jump)
2911                     {
2912                         state = STATE.DIZZY_TRIES_WATER_FLOWERS_MESSAGE;
2913                         break switch_label;
2914                     }
2915                     if (dizzy_water_flowers_state < 1 &&
2916                         items[inventory[inv_num]].model == "bucket-covered" &&
2917                         abs(the_hero.x-276.0) < 3.0 &&
2918                         abs(the_hero.y+8.1) < 0.5 && !the_hero.jump)
2919                     {
2920                         state = STATE.DIZZY_WATER_FLOWERS_MESSAGE;
2921                         bucket_covered.inventory = false;
2922                         bucket_covered.used = true;
2923                         blanket.inventory = true;
2924                         blanket.used = false;
2925                         inventory[inv_num] += 3;
2926                         dizzy_water_flowers_state = 1;
2927                         the_hero.water_with_bucket_of_water();
2928                         break switch_label;
2929                     }
2930 
2931                     // Location : Garden under tree
2932                     if (ground_garden.frame < 0 &&
2933                         items[inventory[inv_num]].model == "spade" &&
2934                         abs(the_hero.x-326.1) < 3.0 &&
2935                         abs(the_hero.y+6.0) < 0.5 && !the_hero.jump)
2936                     {
2937                         ground_garden.frame = root.frame;
2938                         state = STATE.DIZZY_DIG_MESSAGE;
2939                         the_hero.dig();
2940                         break switch_label;
2941                     }
2942 
2943                     // Location : Cave of light tree
2944                     if (items[inventory[inv_num]].model == "branch" &&
2945                         "Martian_Engineer_Takes_Bucket" in done_dialogs &&
2946                         abs(the_hero.x-12.3) < 1.5 &&
2947                         abs(the_hero.y+7.3) < 0.5 && !the_hero.jump)
2948                     {
2949                         state = STATE.DIZZY_HOLD_BRANCH_UNDER_DROP;
2950                         branch.inventory = false;
2951                         branch.used = true;
2952                         light_branch.inventory = true;
2953                         light_branch.used = false;
2954                         inventory[inv_num]++;
2955                         break switch_label;
2956                     }
2957                     if (items[inventory[inv_num]].model == "bucket" &&
2958                         "Martian_Engineer_Returns_Bucket" in done_dialogs &&
2959                         abs(the_hero.x-12.3) < 1.5 &&
2960                         abs(the_hero.y+7.3) < 0.5 && !the_hero.jump)
2961                     {
2962                         state = STATE.DIZZY_TRIES_TO_GET_WATER;
2963                         break switch_label;
2964                     }
2965                     if (items[inventory[inv_num]].model == "bucket-with-ground" &&
2966                         "Martian_Engineer_Returns_Bucket" in done_dialogs &&
2967                         abs(the_hero.x-12.3) < 1.5 &&
2968                         abs(the_hero.y+7.3) < 0.5 && !the_hero.jump)
2969                     {
2970                         state = STATE.DIZZY_GET_LIGHT_WATER;
2971                         foreach(i, ref item; items)
2972                         {
2973                             if (item.model == "bucket-with-light-water")
2974                             {
2975                                 items[inventory[inv_num]].inventory = false;
2976                                 items[inventory[inv_num]].used = true;
2977                                 inventory[inv_num] = i;
2978                                 item.inventory = true;
2979                                 break;
2980                             }
2981                         }
2982                         break switch_label;
2983                     }
2984 
2985                     // Location : Door in the cave of light tree
2986                     if (items[inventory[inv_num]].model == "key" &&
2987                         abs(the_hero.x-16.8) < 1.5 &&
2988                         abs(the_hero.y-0.6) < 0.5 && !the_hero.jump)
2989                     {
2990                         state = STATE.DIZZY_OPEN_DOOR;
2991                         key.inventory = false;
2992                         key.used = true;
2993                         inventory = inventory[0..inv_num] ~ inventory[inv_num+1..$];
2994                         door.y += 17.0f;
2995                         break switch_label;
2996                     }
2997 
2998                     // Location : Cave with grasshopper
2999                     if (ground_cave.frame < 0 &&
3000                         items[inventory[inv_num]].model == "spade" &&
3001                         abs(the_hero.x-30.3) < 3.0 &&
3002                         abs(the_hero.y-62.7) < 0.5 && !the_hero.jump)
3003                     {
3004                         state = STATE.DIZZY_DIG2_MESSAGE;
3005                         break switch_label;
3006                     }
3007                     if (items[inventory[inv_num]].model == "bucket" &&
3008                         "Martian_Engineer_Returns_Bucket" in done_dialogs &&
3009                         abs(the_hero.x-30.3) < 1.5 &&
3010                         abs(the_hero.y-62.7) < 0.5 && !the_hero.jump)
3011                     {
3012                         state = STATE.DIZZY_PUT_GROUND_TO_THE_BUCKET;
3013                         foreach(i, ref item; items)
3014                         {
3015                             if (item.model == "bucket-with-ground")
3016                             {
3017                                 items[inventory[inv_num]].inventory = false;
3018                                 items[inventory[inv_num]].used = true;
3019                                 inventory[inv_num] = i;
3020                                 item.inventory = true;
3021                                 break;
3022                             }
3023                         }
3024                         break switch_label;
3025                     }
3026 
3027                     // Location : The Castle, near Zaks
3028                     if (ground_castle.frame < 0 &&
3029                         items[inventory[inv_num]].model == "spade" &&
3030                         abs(the_hero.x-476.0) < 3.0 &&
3031                         abs(the_hero.y+159.0) < 0.5 && !the_hero.jump)
3032                     {
3033                         state = STATE.DIZZY_DIG3_MESSAGE;
3034                         break switch_label;
3035                     }
3036 
3037                     // Location : The Castle, near Zaks, in the shelter
3038                     if (ground_castle.frame >= 0 &&
3039                         items[inventory[inv_num]].model == "whistle" &&
3040                         abs(the_hero.x-473.9) < 3.0 &&
3041                         abs(the_hero.y+159.5) < 0.5 && !the_hero.jump)
3042                     {
3043                         if (!all_items_in_the_castle())
3044                         {
3045                             state = STATE.NOT_ALL_ITEMS_IN_THE_CASTLE_MESSAGE;
3046                             break switch_label;
3047                         }
3048                         else if (!rope.in_the_castle())
3049                         {
3050                             state = STATE.ROPE_NOT_IN_THE_CASTLE_MESSAGE;
3051                             break switch_label;
3052                         }
3053                         else
3054                         {
3055                             state = STATE.DIZZY_WHISTLE_MESSAGE;
3056                             inventory = inventory[0..inv_num] ~ inventory[inv_num+1..$];
3057                             whistle.inventory = false;
3058                             whistle.used = true;
3059                             break switch_label;
3060                         }
3061                     }
3062 
3063                     // Location : The bug place
3064                     if ((items[inventory[inv_num]].model == "stone1" ||
3065                         items[inventory[inv_num]].model == "stone2") &&
3066                         abs(the_hero.x-242.6) < 3.0 &&
3067                         abs(the_hero.y+5.0) < 0.5 && !the_hero.jump)
3068                     {
3069                         state = STATE.DIZZY_PUT_STONE_MESSAGE;
3070 
3071                         if ( !stone1.inventory && abs(stone1.x - 242.6) < 0.1 && abs(stone1.y + 5.2) < 0.1 ||
3072                              !stone2.inventory && abs(stone2.x - 242.6) < 0.1 && abs(stone2.y + 5.2) < 0.1 )
3073                         {
3074                             items[inventory[inv_num]].inventory = false;
3075                             items[inventory[inv_num]].x = 242.6;
3076                             items[inventory[inv_num]].y = -4.4;
3077                             items[inventory[inv_num]].z = the_hero.z;
3078                             inventory = inventory[0..inv_num]~ inventory[inv_num+1..$];
3079                         }
3080                         else
3081                         {
3082                             items[inventory[inv_num]].inventory = false;
3083                             items[inventory[inv_num]].x = 242.6;
3084                             items[inventory[inv_num]].y = -5.2;
3085                             items[inventory[inv_num]].z = the_hero.z;
3086                             inventory = inventory[0..inv_num]~ inventory[inv_num+1..$];
3087                         }
3088 
3089                         break switch_label;
3090                     }
3091 
3092                     // Location : Lair of shallow habitats
3093                     if (items[inventory[inv_num]].model == "fish-rod" &&
3094                         bug_item.inventory &&
3095                         abs(the_hero.x-371.5) < 1.5 &&
3096                         abs(the_hero.y+104.8) < 0.5 && !the_hero.jump)
3097                     {
3098                         state = STATE.DIZZY_CATCH_FISH_MESSAGE;
3099                         
3100                         foreach(i, ref item; items)
3101                         {
3102                             if (item.model == "fish-item")
3103                             {
3104                                 items[inventory[inv_num]].inventory = false;
3105                                 items[inventory[inv_num]].used = true;
3106                                 inventory[inv_num] = i;
3107                                 item.inventory = true;
3108                                 fish.hide();
3109                                 break;
3110                             }
3111                         }
3112                         
3113                         break switch_label;
3114                     }
3115 
3116                     // Location : Lair of deep-sea dweller
3117                     if (items[inventory[inv_num]].model == "short-rope" &&
3118                         fish_item.inventory &&
3119                         abs(the_hero.x-274.0) < 4.0 &&
3120                         abs(the_hero.y+122.0) < 6.0)
3121                     {
3122                         state = STATE.DIZZY_CATCH_SQUID_MESSAGE;
3123                         
3124                         foreach(i, ref item; items)
3125                         {
3126                             if (item.model == "squid-item")
3127                             {
3128                                 items[inventory[inv_num]].inventory = false;
3129                                 items[inventory[inv_num]].used = true;
3130                                 inventory[inv_num] = i;
3131                                 item.inventory = true;
3132                                 squid.hide();
3133                                 break;
3134                             }
3135                         }
3136                         
3137                         break switch_label;
3138                     }
3139 
3140                     // Location: Near bug
3141                     if (items[inventory[inv_num]].model == "nettle" &&
3142                         abs(the_hero.x-bug.x) < 3.0 &&
3143                         abs(the_hero.y-bug.y) < 0.5 && !the_hero.jump)
3144                     {
3145                         if ( (!stone1.inventory && abs(stone1.x - 242.6) < 0.1 && abs(stone1.y + 4.4) < 0.1 ||
3146                               !stone2.inventory && abs(stone2.x - 242.6) < 0.1 && abs(stone2.y + 4.4) < 0.1) &&
3147                               bug.x < 242.6 )
3148                         {
3149                             state = STATE.DIZZY_CATCH_BUG_MESSAGE;
3150 
3151                             foreach(i, ref item; items)
3152                             {
3153                                 if (item.model == "bug")
3154                                 {
3155                                     items[inventory[inv_num]].inventory = false;
3156                                     items[inventory[inv_num]].used = true;
3157                                     inventory[inv_num] = i;
3158                                     item.inventory = true;
3159                                     bug.kill();
3160                                     break;
3161                                 }
3162                             }
3163                         }
3164                         else
3165                         {
3166                             state = STATE.DIZZY_TRY_CATCH_BUG_MESSAGE;
3167                         }
3168                         
3169                         break switch_label;
3170                     }
3171 
3172                     // Location: Near bug
3173                     if (items[inventory[inv_num]].model == "psychotropic-spray" &&
3174                         !bug.sprayed &&
3175                         abs(the_hero.x-bug.x) < 3.0 &&
3176                         abs(the_hero.y-bug.y) < 0.5 && !the_hero.jump)
3177                     {
3178                         state = STATE.DIZZY_SPRAYED_BUG_MESSAGE;
3179                         bug.spray();
3180                         
3181                         break switch_label;
3182                     }
3183 
3184                     // Location: Near grasshopper
3185                     if (items[inventory[inv_num]].model == "psychotropic-spray" &&
3186                         !grasshopper.sprayed &&
3187                         abs(the_hero.x-grasshopper.x) < 3.0 &&
3188                         abs(the_hero.y-grasshopper.y) < 0.5 && !the_hero.jump)
3189                     {
3190                         state = STATE.DIZZY_SPRAYED_GRASSHOPPER_MESSAGE;
3191                         grasshopper.spray();
3192                         
3193                         break switch_label;
3194                     }
3195                     
3196                     if (dizzy_water_flowers_state < 1 &&
3197                         items[inventory[inv_num]].model == "blanket" &&
3198                         bucket_of_water.inventory)
3199                     {
3200                         state = STATE.DIZZY_COVERED_BUCKET_MESSAGE;
3201                         break switch_label;
3202                     }
3203                     
3204                     items[inventory[inv_num]].inventory = false;
3205                     items[inventory[inv_num]].x = the_hero.x;
3206                     items[inventory[inv_num]].y = the_hero.y;
3207                     items[inventory[inv_num]].z = the_hero.z;
3208                     inventory = inventory[0..inv_num]~ inventory[inv_num+1..$];
3209                 }
3210                 state = STATE.NO_DIALOGS;
3211                 break;
3212             case STATE.ENERGY_STAR:
3213             case STATE.TOO_MANY_ITEMS:
3214             case STATE.MARTIAN_AGRONOMIST_HELLO6:
3215             case STATE.DIZZY_TRIES_FILL_BUCKET_MESSAGE:
3216             case STATE.DIZZY_THROW_METEORITE_MESSAGE:
3217             case STATE.MARTIAN_AGRONOMIST_THANKS:
3218             case STATE.MARTIAN_ENGINEER_TAKES_BUCKET1:
3219             case STATE.DIZZY_HOLD_BRANCH_UNDER_DROP:
3220             case STATE.DIZZY_OPEN_DOOR:
3221             case STATE.BAG_FOUND:
3222             case STATE.DIZZY_CATCH_GRASSHOPPER_MESSAGE:
3223             case STATE.MARTIAN_CHEMIST_NO_GRASSHOPPER:
3224             case STATE.MARTIAN_CHEMIST_NO_BIRD:
3225             case STATE.MARTIAN_CHEMIST_NO_GRASSHOPPERS_POISON:
3226             case STATE.MARTIAN_CHEMIST_NO_BUG:
3227             case STATE.MARTIAN_CHEMIST_NO_FISH:
3228             case STATE.MARTIAN_CHEMIST_NO_SQUID:
3229             case STATE.MARTIAN_CHEMIST_NO_BUGS_POISON:
3230             case STATE.MARTIAN_CHEMIST_THANK_YOU:
3231             case STATE.MARTIAN_CHEMIST_NEED_WATER_FROM_LIGHT_TREE_CAVE:
3232             case STATE.DIZZY_PUT_STONE_MESSAGE:
3233             case STATE.DIZZY_TRY_CATCH_BUG_MESSAGE:
3234             case STATE.DIZZY_CATCH_BUG_MESSAGE:
3235             case STATE.DIZZY_UNTIED_SHORT_ROPE_MESSAGE:
3236             case STATE.DIZZY_CATCH_FISH_MESSAGE:
3237             case STATE.DIZZY_CATCH_SQUID_MESSAGE:
3238             case STATE.DIZZY_TRIES_TO_GET_WATER:
3239             case STATE.DIZZY_PUT_GROUND_TO_THE_BUCKET:
3240             case STATE.DIZZY_GET_LIGHT_WATER:
3241             case STATE.DIZZY_SPRAYED_BUG_MESSAGE:
3242             case STATE.DIZZY_SPRAYED_GRASSHOPPER_MESSAGE:
3243             case STATE.NOT_ALL_ITEMS_IN_THE_CASTLE_MESSAGE:
3244             case STATE.ROPE_NOT_IN_THE_CASTLE_MESSAGE:
3245             case STATE.TO_BE_CONTINUED_MESSAGE:
3246                 state = STATE.NO_DIALOGS;
3247                 break;
3248             case STATE.PIERCED_BY_STALAGMITE:
3249             case STATE.PIERCED_BY_STALACTITE:
3250             case STATE.HIT_BY_METEORITE:
3251             case STATE.DISSOLVED_IN_ACID:
3252             case STATE.BURNED_IN_LAVA:
3253             case STATE.DAMAGED_BY_PIN:
3254             case STATE.HIT_BY_ROCK:
3255             case STATE.BURNED_IN_FLAME:
3256             case STATE.CRUSHED_BY_PRESSURE:
3257                 if ( abs(scrx-420.0) < 1.0 &&
3258                      (abs(scry+17.0) < 1.0 || abs(scry-0.0) < 1.0) )
3259                 {
3260                     if (dizzy_live_after_explosure_quest_state < 0)
3261                     {
3262                         if (baloon.inventory)
3263                         {
3264                             foreach(i, item_num; inventory)
3265                             {
3266                                 if (items[item_num] == baloon)
3267                                 {
3268                                     inventory = inventory[0..i] ~ inventory[i+1..$];
3269                                     break;
3270                                 }
3271                             }
3272                         }
3273                         
3274                         baloon.load(null);
3275                         explosure.load(null);
3276                     }
3277                     the_hero.last_safe = [418.1, 1.0, 0.0];
3278                 }
3279                 the_hero.rise();
3280                 state = STATE.NO_DIALOGS;
3281                 break;
3282             case STATE.MARTIAN_AGRONOMIST_HELLO:
3283             case STATE.MARTIAN_AGRONOMIST_HELLO1:
3284             case STATE.MARTIAN_AGRONOMIST_HELLO2:
3285             case STATE.MARTIAN_AGRONOMIST_HELLO3:
3286             case STATE.MARTIAN_AGRONOMIST_HELLO4:
3287             case STATE.MARTIAN_AGRONOMIST_HELLO5:
3288             case STATE.MARTIAN_CHEMIST_HELLO:
3289             case STATE.MARTIAN_CHEMIST_HELLO1:
3290             case STATE.MARTIAN_CHEMIST_HELLO2:
3291             case STATE.MARTIAN_CHEMIST_HELLO3:
3292             case STATE.MARTIAN_CHEMIST_HELLO4:
3293             case STATE.DIZZY_USED_KNIFE_MESSAGE:
3294             case STATE.DIZZY_THROW_BRANCH_MESSAGE:
3295             case STATE.DIZZY_CUTS_ROPE_MESSAGE:
3296             case STATE.MARTIAN_AGRONOMIST_GIVES_BUCKET:
3297             case STATE.MARTIAN_ENGINEER_RETURNS_PLAYER:
3298             case STATE.MARTIAN_ENGINEER_RETURNS_PLAYER1:
3299             case STATE.MARTIAN_ENGINEER_TAKES_BUCKET:
3300             case STATE.DIZZY_DIG_MESSAGE:
3301             case STATE.ZAKS_SAYS_FAREWELL_WORD:
3302                 state++;
3303                 break;
3304             case STATE.DIZZY_WHISTLE_MESSAGE:
3305                 things_sweep_away_zaks.unhide();
3306                 state++;
3307                 break;
3308             case STATE.THINGS_SWEEP_AWAY_ZAKS_ANIM:
3309                 things_sweep_away_zaks.hide();
3310                 stones.frame = frame;
3311                 stones.tick(gs);
3312                 stone3.x = 413.4;
3313                 stone3.y = -84.3;
3314                 state++;
3315                 break;
3316             case STATE.LOOKING_BOOTH_MESSAGE:
3317                 state = STATE.LOOKING_BOOTH;
3318                 scry += 68.0;
3319                 sl_tid.send(cast(int) round(scrx/30.0),
3320                     cast(int) round(scry/17.0));
3321                 break;
3322             case STATE.LOOKING_BOOTH:
3323                 scry -= 68.0;
3324                 state = STATE.NO_DIALOGS;
3325                 sl_tid.send(cast(int) round(scrx/30.0),
3326                     cast(int) round(scry/17.0));
3327                 break;
3328             case STATE.DIZZY_USED_KNIFE_ANIM:
3329                 dizzy_used_knife_quest_state = 2;
3330                 the_hero.y = -6.0;
3331                 the_hero.reset_anim();
3332                 collision_objects["solid"].remove("BranchForBreak");
3333                 state = STATE.NO_DIALOGS;
3334                 break;
3335             case STATE.DIZZY_THROW_BRANCH_ANIM:
3336             case STATE.DIZZY_CUTS_ROPE_ANIM:
3337             case STATE.DIZZY_DIG_ANIM:
3338             case STATE.HELP:
3339                 break;
3340             case STATE.DIZZY_DIG2_MESSAGE:
3341                 ground_cave.frame = frame;
3342                 grasshopper.change_solid(true);
3343                 state = STATE.NO_DIALOGS;
3344                 break;
3345             case STATE.DIZZY_DIG3_MESSAGE:
3346                 ground_castle.frame = frame;
3347                 state = STATE.NO_DIALOGS;
3348                 break;
3349             case STATE.MARTIAN_ENGINEER_GET_AWAY:
3350                 if (player.x == player.def_x &&
3351                     player.y == player.def_y)
3352                 {
3353                     player.x = 118.0;
3354                     player.y = 0.4;
3355                 }
3356                 the_hero.force_dx = -0.15;
3357                 the_hero.dy = the_hero.JUMP_V;
3358                 state = STATE.NO_DIALOGS;
3359                 break;
3360             case STATE.MARTIAN_AGRONOMIST_ROPE:
3361                 rope.x = 280.9;
3362                 rope.y = 0.8;
3363                 state = STATE.NO_DIALOGS;
3364                 break;
3365             case STATE.MARTIAN_AGRONOMIST_GIVES_BUCKET1:
3366                 bucket.x = 280.9;
3367                 bucket.y = 0.8;
3368                 state = STATE.NO_DIALOGS;
3369                 break;
3370             case STATE.MARTIAN_ENGINEER_TAKES_PLAYER:
3371                 martian_engineer.degrees = 0;
3372                 martian_engineer.z = 2.0;
3373                 state = STATE.NO_DIALOGS;
3374                 break;
3375             case STATE.DIZZY_TIED_ROPE_MESSAGE:
3376                 if (abs(scrx - 420.0) < 1.0 &&
3377                     abs(scry - 0.0) < 1.0)
3378                 {
3379                     rope_state = 1;
3380                     rope1.reinit();
3381                 }
3382 
3383                 if (abs(scrx - 240.0) < 1.0 &&
3384                     abs(scry - 0.0) < 1.0)
3385                 {
3386                     rope_state = 2;
3387                     rope2.reinit();
3388                 }
3389 
3390                 if (abs(scrx - 330.0) < 1.0 &&
3391                     abs(scry + 17.0) < 1.0)
3392                 {
3393                     if (pressprot.x == pressprot.def_x &&
3394                         pressprot.y == pressprot.def_y)
3395                     {
3396                         pressprot.x = 465.9;
3397                         pressprot.y = -6.2;
3398                     }
3399 
3400                     rope_state = 3;
3401                     rope3.reinit();
3402                 }
3403                 
3404                 state = STATE.NO_DIALOGS;
3405                 break;
3406 
3407             case STATE.DIZZY_UNTIED_ROPE_MESSAGE:
3408                 rope_state = 0;
3409                 state = STATE.NO_DIALOGS;
3410                 break;
3411 
3412             case STATE.MARTIAN_CHEMIST_HELLO5:
3413                 stunning_drink.x = 462.0;
3414                 stunning_drink.y = 1.7;
3415                 stunning_drink.z = 0.0;
3416                 state = STATE.NO_DIALOGS;
3417                 break;
3418 
3419             case STATE.DIZZY_DRINK_STUNNING_MESSAGE:
3420                 foreach(i, ref item_num; inventory)
3421                 {
3422                     if (items[item_num] == stunning_drink)
3423                     {
3424                         stunning_drink.used = true;
3425                         bottle.inventory = true;
3426                         item_num++;
3427                         break;
3428                     }
3429                 }
3430                 the_hero.stunning = 10*6000;
3431                 state = STATE.NO_DIALOGS;
3432                 break;
3433 
3434             case STATE.DIZZY_FILL_BUCKET_MESSAGE:
3435                 foreach(i, ref item_num; inventory)
3436                 {
3437                     if (items[item_num] == bucket)
3438                     {
3439                         bucket.inventory = false;
3440                         bucket.used = true;
3441                         bucket_of_water.used = false;
3442                         bucket_of_water.inventory = true;
3443                         item_num++;
3444                         break;
3445                     }
3446                     if (items[item_num] == bucket_of_ice)
3447                     {
3448                         bucket_of_ice.inventory = false;
3449                         bucket_of_ice.used = true;
3450                         bucket_of_water.used = false;
3451                         bucket_of_water.inventory = true;
3452                         item_num--;
3453                         break;
3454                     }
3455                 }
3456                 state = STATE.NO_DIALOGS;
3457                 break;
3458 
3459             case STATE.DIZZY_TRIES_WATER_FLOWERS_MESSAGE:
3460                 foreach(i, ref item_num; inventory)
3461                 {
3462                     if (items[item_num] == bucket_of_water)
3463                     {
3464                         bucket_of_water.inventory = false;
3465                         bucket_of_water.used = true;
3466                         bucket_of_ice.inventory = true;
3467                         bucket_of_ice.used = false;
3468                         item_num++;
3469                         break;
3470                     }
3471                 }
3472                 state = STATE.NO_DIALOGS;
3473                 break;
3474 
3475             case STATE.DIZZY_COVERED_BUCKET_MESSAGE:
3476                 foreach(i, ref item_num; inventory)
3477                 {
3478                     if (items[item_num] == bucket_of_water)
3479                     {
3480                         bucket_of_water.inventory = false;
3481                         bucket_of_water.used = true;
3482                         bucket_covered.inventory = true;
3483                         bucket_covered.used = false;
3484                         item_num += 2;
3485                         break;
3486                     }
3487                 }
3488                 
3489                 foreach(i, ref item_num; inventory)
3490                 {   
3491                     if (items[item_num] == blanket)
3492                     {
3493                         blanket.inventory = false;
3494                         blanket.used = true;
3495                         inventory = inventory[0..i] ~ inventory[i+1..$];
3496                         break;
3497                     }
3498                 }
3499                 
3500                 state = STATE.NO_DIALOGS;
3501                 break;
3502 
3503             case STATE.DIZZY_WATER_FLOWERS_MESSAGE:
3504                 bucket.used = false;
3505                 bucket.x = the_hero.x;
3506                 bucket.y = the_hero.y;
3507                 bucket.z = the_hero.z;
3508 
3509                 the_hero.reset_anim();
3510                 state = STATE.NO_DIALOGS;
3511                 break;
3512 
3513             case STATE.MARTIAN_ENGINEER_RETURNS_PLAYER2:
3514                 player.used = false;
3515                 player.x = the_hero.x - 2.0;
3516                 player.y = the_hero.y;
3517                 player.z = the_hero.z;
3518                 
3519                 state = STATE.NO_DIALOGS;
3520                 break;
3521 
3522             case STATE.MARTIAN_ENGINEER_GIVES_SPADE:
3523                 spade.used = false;
3524                 spade.x = the_hero.x - 2.0;
3525                 spade.y = the_hero.y;
3526                 spade.z = the_hero.z;
3527                 
3528                 state = STATE.NO_DIALOGS;
3529                 break;
3530 
3531             case STATE.MARTIAN_ENGINEER_GIVES_WHISTLE:
3532                 whistle.used = false;
3533                 whistle.x = the_hero.x - 2.0;
3534                 whistle.y = the_hero.y;
3535                 whistle.z = the_hero.z;
3536                 
3537                 state = STATE.NO_DIALOGS;
3538                 break;
3539 
3540             case STATE.MARTIAN_ENGINEER_RETURNS_BUCKET:
3541                 bucket.used = false;
3542                 bucket.x = the_hero.x - 2.0;
3543                 bucket.y = the_hero.y;
3544                 bucket.z = the_hero.z;
3545                 
3546                 state = STATE.NO_DIALOGS;
3547                 break;
3548 
3549             case STATE.MARTIAN_CHEMIST_GIVES_PSYCHOTROPIC_SPRAY:
3550                 psychotropic_spray.used = false;
3551                 psychotropic_spray.x = the_hero.x - 2.0;
3552                 psychotropic_spray.y = the_hero.y;
3553                 psychotropic_spray.z = the_hero.z;
3554 
3555                 bucket.used = false;
3556                 bucket.x = the_hero.x - 4.0;
3557                 bucket.y = the_hero.y;
3558                 bucket.z = the_hero.z;
3559 
3560                 bug.killed = false;
3561                 grasshopper.killed = false;
3562                 grasshopper.change_solid(false);
3563 
3564                 track = 4;
3565                 music_start_tick = cast(long)SDL_GetTicks();
3566                 play_music();
3567                 
3568                 state = STATE.NO_DIALOGS;
3569                 break;
3570 
3571             case STATE.STONES_CRASHES_MESSAGE:
3572                 zaks.y -= 17.0;
3573                 
3574                 track = 0;
3575                 music_start_tick = cast(long)SDL_GetTicks();
3576                 play_music();
3577                 
3578                 state = STATE.NO_DIALOGS;
3579                 break;
3580         }
3581     }
3582 
3583     void load(string[string] s)
3584     {
3585         if ("frame" in s)
3586             frame = s["frame"].to!(long);
3587         else
3588             frame = 0;
3589 
3590         temp_message_frame_from = 0;
3591         temp_message_frame_to = 0;
3592 
3593         if ("lang" in s)
3594             lang = s["lang"].to!(LANG);
3595         else
3596             lang = LANG.EN;
3597 
3598         if ("track" in s)
3599         {
3600             int tr = s["track"].to!(int);
3601             if (track != tr)
3602             {
3603                 track = tr;
3604                 play_music();
3605             }
3606         }
3607         else
3608         {
3609             if (track != 0)
3610             {
3611                 track = 0;
3612                 play_music();
3613             }
3614         }   
3615         
3616         num_stars = 0;
3617         foreach(star; stars)
3618         {
3619             star.load(s);
3620             if (star.taken)
3621                 num_stars++;
3622         }
3623 
3624         inventory = [];
3625         foreach(i, item; items)
3626         {
3627             item.load(s);
3628             if (item.inventory)
3629                 inventory ~= i;
3630         }
3631 
3632         max_items = (bag.used ? 5 : 3);
3633 
3634         foreach(animation; animations)
3635             animation.load(s);
3636 
3637         the_hero.load(s);
3638         bag_bug_anim.load(s);
3639         
3640         done_dialogs = null;
3641         foreach(d; ["Martian_Agronomist_Hello",
3642                     "Martian_Agronomist_Rope",
3643                     "Martian_Engineer_Takes_Player",
3644                     "Martian_Chemist_Hello",
3645                     "Martian_Agronomist_Gives_Bucket",
3646                     "Martian_Agronomist_Thanks",
3647                     "Martian_Engineer_Returns_Player",
3648                     "Martian_Engineer_Takes_Bucket",
3649                     "Martian_Engineer_Gives_Spade",
3650                     "Martian_Engineer_Returns_Bucket",])
3651         {
3652             if ("dialog"~d in s)
3653             {
3654                 done_dialogs[d] = true;
3655             }
3656         }
3657 
3658         if ("dizzy_used_knife" in s)
3659         {
3660             dizzy_used_knife_quest_state = s["dizzy_used_knife"].to!(int);
3661             collision_objects["solid"]["BranchForBreak"] = null;
3662             collision_objects["solid"].remove("BranchForBreak");
3663             reset_collision_cache();
3664         }
3665         else
3666         {
3667             dizzy_used_knife_quest_state = -1;
3668             collision_objects["solid"]["BranchForBreak"] = collision_objects["temp-solid"]["BranchForBreak"];
3669             reset_collision_cache();
3670         }
3671 
3672         if ("dizzy_cuts_rope" in s)
3673         {
3674             dizzy_cuts_rope_quest_state = 0;
3675             dizzy_throw_branch_quest_state = 5;
3676         }
3677         else
3678         {
3679             dizzy_cuts_rope_quest_state = -1;
3680             dizzy_throw_branch_quest_state = -1;
3681         }
3682 
3683         if ("dizzy_live_after_explosure" in s)
3684         {
3685             dizzy_live_after_explosure_quest_state = 0;
3686         }
3687         else
3688             dizzy_live_after_explosure_quest_state = -1;
3689 
3690         if ("rope_state" in s)
3691             rope_state = s["rope_state"].to!(int);
3692         else rope_state = 0;
3693 
3694         if ("dizzy_fields_garden" in s)
3695             dizzy_water_flowers_state = s["dizzy_fields_garden"].to!(int);
3696         else if ("dizzy_water_flowers" in s)
3697             dizzy_water_flowers_state = s["dizzy_water_flowers"].to!(int);
3698         else dizzy_water_flowers_state = -1;
3699 
3700         if (meteorite.x != meteorite.def_x ||
3701             meteorite.y != meteorite.def_y)
3702             wait_meteorite = 2;
3703         else
3704             wait_meteorite = -1;
3705 
3706         if (bird.fly == 2)
3707             wait_meteorite2 = 2;
3708         else
3709             wait_meteorite2 = -1;
3710     }
3711 
3712     void save(ref string[string] s)
3713     {
3714         foreach(star; stars)
3715             star.save(s);
3716 
3717         foreach(item; items)
3718             item.save(s);
3719 
3720         foreach(animation; animations)
3721             animation.save(s);
3722 
3723         the_hero.save(s);
3724         bag_bug_anim.save(s);
3725         
3726         foreach(d; ["Martian_Agronomist_Hello",
3727                     "Martian_Agronomist_Rope",
3728                     "Martian_Engineer_Takes_Player",
3729                     "Martian_Chemist_Hello",
3730                     "Martian_Agronomist_Gives_Bucket",
3731                     "Martian_Agronomist_Thanks",
3732                     "Martian_Engineer_Returns_Player",
3733                     "Martian_Engineer_Takes_Bucket",
3734                     "Martian_Engineer_Gives_Spade",
3735                     "Martian_Engineer_Returns_Bucket",])
3736         {
3737             if (d in done_dialogs)
3738             {
3739                 s["dialog"~d] = "done";
3740             }
3741         }
3742 
3743         if (dizzy_used_knife_quest_state >= 2)
3744             s["dizzy_used_knife"] = dizzy_used_knife_quest_state.to!(string);
3745 
3746         if (dizzy_cuts_rope_quest_state >= 0 &&
3747             dizzy_throw_branch_quest_state >= 5)
3748             s["dizzy_cuts_rope"] = "Done";
3749 
3750         if (dizzy_live_after_explosure_quest_state >= 0)
3751             s["dizzy_live_after_explosure"] = "Done";
3752 
3753         if (rope_state != 0)
3754             s["rope_state"] = rope_state.to!(string);
3755 
3756         if (dizzy_water_flowers_state >= 0)
3757             s["dizzy_water_flowers"] = dizzy_water_flowers_state.to!(string);
3758 
3759         s["frame"] = frame.to!(string);
3760         s["lang"] = lang.to!(string);
3761         s["track"] = track.to!(string);
3762     }
3763 
3764     void restart(GlobalState gs)
3765     {   
3766         if (!(keys & CTRL_KEY)) return;
3767 
3768         load(cast(string[string]) null);
3769     }
3770 
3771     void load(GlobalState gs)
3772     {
3773         if (!(keys & CTRL_KEY)) return;
3774         if (state != STATE.NO_DIALOGS) return;
3775         
3776         auto s = .load();
3777         load(s);
3778     }
3779 
3780     void save(GlobalState gs)
3781     {        
3782         if (keys & (LEFT_KEY | RIGHT_KEY))
3783         {
3784             print_message(TEMP_MESSAGES.CANT_SAVE_IN_THE_MOVING);
3785             return;
3786         }
3787         
3788         if (dizzy_throw_branch_quest_state >= 0 && dizzy_cuts_rope_quest_state < 0 ||
3789             dizzy_throw_branch_quest_state < 5 && dizzy_cuts_rope_quest_state >= 0)
3790         {
3791             print_message(TEMP_MESSAGES.CANT_SAVE_DURING_THE_QUEST);
3792             return;
3793         }
3794 
3795         if (the_hero.lives < 0)
3796         {
3797             print_message(TEMP_MESSAGES.NEGATIVE_LIVES);
3798             return;
3799         }
3800 
3801         if (state != STATE.NO_DIALOGS) return;
3802         
3803         string[string] s;
3804         save(s);
3805         .save(s);
3806 
3807         print_message(TEMP_MESSAGES.SAVED);
3808     }
3809 
3810     void help(GlobalState gs)
3811     {
3812         if (state == STATE.HELP) state = STATE.NO_DIALOGS;
3813         else if (state == STATE.NO_DIALOGS) state = STATE.HELP;
3814     }
3815 
3816     void play_music()
3817     {
3818         if (music)
3819         {
3820             if (Mix_PlayMusic(musics[track], -1) == -1)
3821             {
3822                 writefln("Mix_PlayMusic: %s",
3823                     Mix_GetError().to!(string)());
3824             }
3825     
3826             if(Mix_SetMusicPosition((
3827                 (SDL_GetTicks() - music_start_tick)/1000.0)%
3828                 music_len[track]) == -1) {
3829                 writefln("Mix_SetMusicPosition: %s\n",
3830                     Mix_GetError().to!(string)());
3831             }
3832             
3833             print_message(TEMP_MESSAGES.PLAYS, " "~music_name[track]);
3834         }
3835         else
3836         {
3837             Mix_HaltMusic();
3838         }
3839     }
3840 
3841     void turn_music(GlobalState gs)
3842     {
3843         music = !music;
3844         play_music();
3845     }
3846 
3847     void turn_sounds(GlobalState gs)
3848     {
3849         the_hero.sounds = !the_hero.sounds;
3850 
3851         if (!the_hero.sounds)
3852         {
3853             Mix_HaltChannel(-1);
3854         }
3855     }
3856 
3857     void
3858     setup_keybar(GlobalState gs)
3859     {
3860         gs.keybar.handlers.clear();
3861         gs.keybar.handlers_down.clear();
3862         gs.keybar.handlers_double.clear();
3863         
3864         gs.keybar.handlers_down[SDL_SCANCODE_Q] = KeyHandler(&quit, ("Quit"), "exit.png");
3865         gs.keybar.handlers_down[SDL_SCANCODE_PRINTSCREEN] = KeyHandler(toDelegate(&make_screenshot), ("Make screenshot"), "Prt Sc");
3866         gs.keybar.handlers_down[SDL_SCANCODE_P] = KeyHandler(toDelegate(&pause), ("Pause"), "Pause");
3867 
3868         gs.keybar.handlers_down[SDL_SCANCODE_LEFT] = KeyHandler(&start_left, ("Left"), "Left");
3869         gs.keybar.handlers[SDL_SCANCODE_LEFT] = KeyHandler(&stop_left, ("Left"), "Left");
3870         gs.keybar.handlers_down[SDL_SCANCODE_RIGHT] = KeyHandler(&start_right, ("Right"), "Right");
3871         gs.keybar.handlers[SDL_SCANCODE_RIGHT] = KeyHandler(&stop_right, ("Right"), "Right");
3872         gs.keybar.handlers_down[SDL_SCANCODE_UP] = KeyHandler(&start_jump, ("Jump"), "Jump");
3873         gs.keybar.handlers[SDL_SCANCODE_UP] = KeyHandler(&stop_jump, ("Jump"), "Jump");
3874         gs.keybar.handlers_down[SDL_SCANCODE_DOWN] = KeyHandler(&down, ("Down"), "Down");
3875         gs.keybar.handlers[SDL_SCANCODE_DOWN] = KeyHandler(&stop_down, ("Down"), "Down");
3876         gs.keybar.handlers_down[SDL_SCANCODE_RETURN] = KeyHandler(&action, ("Action"), "Action");
3877 
3878         gs.keybar.handlers_down[SDL_SCANCODE_Z] = KeyHandler(&start_left, ("Left"), "Left");
3879         gs.keybar.handlers[SDL_SCANCODE_Z] = KeyHandler(&stop_left, ("Left"), "Left");
3880         gs.keybar.handlers_down[SDL_SCANCODE_X] = KeyHandler(&start_right, ("Right"), "Right");
3881         gs.keybar.handlers[SDL_SCANCODE_X] = KeyHandler(&stop_right, ("Right"), "Right");
3882         gs.keybar.handlers_down[SDL_SCANCODE_K] = KeyHandler(&start_jump, ("Jump"), "Jump");
3883         gs.keybar.handlers[SDL_SCANCODE_K] = KeyHandler(&stop_jump, ("Jump"), "Jump");
3884         gs.keybar.handlers_down[SDL_SCANCODE_M] = KeyHandler(&down, ("Down"), "Down");
3885         gs.keybar.handlers[SDL_SCANCODE_M] = KeyHandler(&stop_down, ("Down"), "Down");
3886 
3887         gs.keybar.handlers_down[SDL_SCANCODE_SPACE] = KeyHandler(&start_jump, ("Jump"), "Jump");
3888         gs.keybar.handlers[SDL_SCANCODE_SPACE] = KeyHandler(&stop_jump, ("Jump"), "Jump");
3889 
3890         gs.keybar.handlers_down[SDL_SCANCODE_LCTRL] = KeyHandler(&ctrl_down, ("Ctrl"), "Ctrl");
3891         gs.keybar.handlers[SDL_SCANCODE_LCTRL] = KeyHandler(&ctrl_up, ("Ctrl"), "Ctrl");
3892         gs.keybar.handlers_down[SDL_SCANCODE_LSHIFT] = KeyHandler(&shift_down, ("Shift"), "Shift");
3893         gs.keybar.handlers[SDL_SCANCODE_LSHIFT] = KeyHandler(&shift_up, ("Shift"), "Shift");
3894         
3895         gs.keybar.handlers_down[SDL_SCANCODE_C] = KeyHandler(&print_coords, ("Print Coords"), "Coords");
3896         gs.keybar.handlers_down[SDL_SCANCODE_S] = KeyHandler(&switch_slow, ("Switch Slow"), "Slow");
3897         gs.keybar.handlers_down[SDL_SCANCODE_E] = KeyHandler(&switch_sensors, ("Show Sensors"), "Sensors");
3898         gs.keybar.handlers_down[SDL_SCANCODE_U] = KeyHandler(&turn_music, ("On/Off Music"), "Music");
3899         gs.keybar.handlers_down[SDL_SCANCODE_O] = KeyHandler(&turn_sounds, ("On/Off Sounds"), "Sounds");
3900 
3901         gs.keybar.handlers_down[SDL_SCANCODE_ESCAPE] = KeyHandler(&help, ("Help"), "Help");
3902 
3903         gs.keybar.handlers_down[SDL_SCANCODE_1] = KeyHandler(&the_hero.change_costume, ("Change Costume"), "Cost");
3904         gs.keybar.handlers_down[SDL_SCANCODE_2] = KeyHandler(&change_language, ("Change Language"), "Lang");
3905 
3906         gs.keybar.handlers_down[SDL_SCANCODE_R] = KeyHandler(&restart, ("Restart"), "Restart");
3907         gs.keybar.handlers_down[SDL_SCANCODE_L] = KeyHandler(&load, ("Load"), "Load");
3908     }
3909 }
3910